diff options
-rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 40 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 14 |
2 files changed, 23 insertions, 31 deletions
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index d4cc9dd04..0bc3ff115 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Utilities for LSP-related boilerplate code. | 1 | //! Utilities for LSP-related boilerplate code. |
2 | use std::{borrow::Cow, error::Error, ops::Range}; | 2 | use std::{error::Error, ops::Range}; |
3 | 3 | ||
4 | use lsp_server::Notification; | 4 | use lsp_server::Notification; |
5 | use ra_db::Canceled; | 5 | use ra_db::Canceled; |
@@ -84,8 +84,8 @@ impl GlobalState { | |||
84 | pub(crate) fn apply_document_changes( | 84 | pub(crate) fn apply_document_changes( |
85 | old_text: &mut String, | 85 | old_text: &mut String, |
86 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, | 86 | content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>, |
87 | mut line_index: Cow<'_, LineIndex>, | ||
88 | ) { | 87 | ) { |
88 | let mut line_index = LineIndex::new(old_text); | ||
89 | // The changes we got must be applied sequentially, but can cross lines so we | 89 | // The changes we got must be applied sequentially, but can cross lines so we |
90 | // have to keep our line index updated. | 90 | // have to keep our line index updated. |
91 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we | 91 | // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we |
@@ -110,7 +110,7 @@ pub(crate) fn apply_document_changes( | |||
110 | match change.range { | 110 | match change.range { |
111 | Some(range) => { | 111 | Some(range) => { |
112 | if !index_valid.covers(range.end.line) { | 112 | if !index_valid.covers(range.end.line) { |
113 | line_index = Cow::Owned(LineIndex::new(old_text)); | 113 | line_index = LineIndex::new(&old_text); |
114 | } | 114 | } |
115 | index_valid = IndexValid::UpToLineExclusive(range.start.line); | 115 | index_valid = IndexValid::UpToLineExclusive(range.start.line); |
116 | let range = from_proto::text_range(&line_index, range); | 116 | let range = from_proto::text_range(&line_index, range); |
@@ -145,15 +145,10 @@ mod tests { | |||
145 | }; | 145 | }; |
146 | } | 146 | } |
147 | 147 | ||
148 | fn run(text: &mut String, changes: Vec<TextDocumentContentChangeEvent>) { | ||
149 | let line_index = Cow::Owned(LineIndex::new(&text)); | ||
150 | super::apply_document_changes(text, changes, line_index); | ||
151 | } | ||
152 | |||
153 | let mut text = String::new(); | 148 | let mut text = String::new(); |
154 | run(&mut text, vec![]); | 149 | apply_document_changes(&mut text, vec![]); |
155 | assert_eq!(text, ""); | 150 | assert_eq!(text, ""); |
156 | run( | 151 | apply_document_changes( |
157 | &mut text, | 152 | &mut text, |
158 | vec![TextDocumentContentChangeEvent { | 153 | vec![TextDocumentContentChangeEvent { |
159 | range: None, | 154 | range: None, |
@@ -162,36 +157,39 @@ mod tests { | |||
162 | }], | 157 | }], |
163 | ); | 158 | ); |
164 | assert_eq!(text, "the"); | 159 | assert_eq!(text, "the"); |
165 | run(&mut text, c![0, 3; 0, 3 => " quick"]); | 160 | apply_document_changes(&mut text, c![0, 3; 0, 3 => " quick"]); |
166 | assert_eq!(text, "the quick"); | 161 | assert_eq!(text, "the quick"); |
167 | run(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); | 162 | apply_document_changes(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); |
168 | assert_eq!(text, "quick foxes"); | 163 | assert_eq!(text, "quick foxes"); |
169 | run(&mut text, c![0, 11; 0, 11 => "\ndream"]); | 164 | apply_document_changes(&mut text, c![0, 11; 0, 11 => "\ndream"]); |
170 | assert_eq!(text, "quick foxes\ndream"); | 165 | assert_eq!(text, "quick foxes\ndream"); |
171 | run(&mut text, c![1, 0; 1, 0 => "have "]); | 166 | apply_document_changes(&mut text, c![1, 0; 1, 0 => "have "]); |
172 | assert_eq!(text, "quick foxes\nhave dream"); | 167 | assert_eq!(text, "quick foxes\nhave dream"); |
173 | run(&mut text, c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"]); | 168 | apply_document_changes( |
169 | &mut text, | ||
170 | c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], | ||
171 | ); | ||
174 | assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); | 172 | assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); |
175 | run(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); | 173 | apply_document_changes(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]); |
176 | assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); | 174 | assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); |
177 | run( | 175 | apply_document_changes( |
178 | &mut text, | 176 | &mut text, |
179 | c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], | 177 | c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], |
180 | ); | 178 | ); |
181 | assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); | 179 | assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); |
182 | run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); | 180 | apply_document_changes(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); |
183 | assert_eq!(text, "the quick \nthey have quiet dreams\n"); | 181 | assert_eq!(text, "the quick \nthey have quiet dreams\n"); |
184 | 182 | ||
185 | text = String::from("❤️"); | 183 | text = String::from("❤️"); |
186 | run(&mut text, c![0, 0; 0, 0 => "a"]); | 184 | apply_document_changes(&mut text, c![0, 0; 0, 0 => "a"]); |
187 | assert_eq!(text, "a❤️"); | 185 | assert_eq!(text, "a❤️"); |
188 | 186 | ||
189 | text = String::from("a\nb"); | 187 | text = String::from("a\nb"); |
190 | run(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); | 188 | apply_document_changes(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); |
191 | assert_eq!(text, "adcb"); | 189 | assert_eq!(text, "adcb"); |
192 | 190 | ||
193 | text = String::from("a\nb"); | 191 | text = String::from("a\nb"); |
194 | run(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); | 192 | apply_document_changes(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); |
195 | assert_eq!(text, "ațc\ncb"); | 193 | assert_eq!(text, "ațc\ncb"); |
196 | } | 194 | } |
197 | } | 195 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 0ace4cb45..51626fcd5 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -1,14 +1,13 @@ | |||
1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP | 1 | //! The main loop of `rust-analyzer` responsible for dispatching LSP |
2 | //! requests/replies and notifications back to the client. | 2 | //! requests/replies and notifications back to the client. |
3 | use std::{ | 3 | use std::{ |
4 | borrow::Cow, | ||
5 | env, fmt, panic, | 4 | env, fmt, panic, |
6 | time::{Duration, Instant}, | 5 | time::{Duration, Instant}, |
7 | }; | 6 | }; |
8 | 7 | ||
9 | use crossbeam_channel::{select, Receiver}; | 8 | use crossbeam_channel::{select, Receiver}; |
10 | use lsp_server::{Connection, Notification, Request, Response}; | 9 | use lsp_server::{Connection, Notification, Request, Response}; |
11 | use lsp_types::{notification::Notification as _, DidChangeTextDocumentParams}; | 10 | use lsp_types::notification::Notification as _; |
12 | use ra_db::VfsPath; | 11 | use ra_db::VfsPath; |
13 | use ra_ide::{Canceled, FileId}; | 12 | use ra_ide::{Canceled, FileId}; |
14 | use ra_prof::profile; | 13 | use ra_prof::profile; |
@@ -422,20 +421,15 @@ impl GlobalState { | |||
422 | })? | 421 | })? |
423 | .on::<lsp_types::notification::DidChangeTextDocument>(|this, params| { | 422 | .on::<lsp_types::notification::DidChangeTextDocument>(|this, params| { |
424 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { | 423 | if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { |
425 | let DidChangeTextDocumentParams { text_document, content_changes } = params; | 424 | let doc = this.mem_docs.get_mut(&path).unwrap(); |
426 | let vfs = &mut this.vfs.write().0; | 425 | let vfs = &mut this.vfs.write().0; |
427 | let world = this.snapshot(); | ||
428 | let file_id = vfs.file_id(&path).unwrap(); | 426 | let file_id = vfs.file_id(&path).unwrap(); |
429 | |||
430 | // let file_id = vfs.file_id(&path).unwrap(); | ||
431 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); | 427 | let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap(); |
432 | let line_index = world.analysis.file_line_index(file_id)?; | 428 | apply_document_changes(&mut text, params.content_changes); |
433 | apply_document_changes(&mut text, content_changes, Cow::Borrowed(&line_index)); | ||
434 | 429 | ||
435 | // The version passed in DidChangeTextDocument is the version after all edits are applied | 430 | // The version passed in DidChangeTextDocument is the version after all edits are applied |
436 | // so we should apply it before the vfs is notified. | 431 | // so we should apply it before the vfs is notified. |
437 | let doc = this.mem_docs.get_mut(&path).unwrap(); | 432 | doc.version = params.text_document.version; |
438 | doc.version = text_document.version; | ||
439 | 433 | ||
440 | vfs.set_file_contents(path.clone(), Some(text.into_bytes())); | 434 | vfs.set_file_contents(path.clone(), Some(text.into_bytes())); |
441 | } | 435 | } |