aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs40
-rw-r--r--crates/rust-analyzer/src/main_loop.rs14
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.
2use std::{borrow::Cow, error::Error, ops::Range}; 2use std::{error::Error, ops::Range};
3 3
4use lsp_server::Notification; 4use lsp_server::Notification;
5use ra_db::Canceled; 5use ra_db::Canceled;
@@ -84,8 +84,8 @@ impl GlobalState {
84pub(crate) fn apply_document_changes( 84pub(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.
3use std::{ 3use std::{
4 borrow::Cow,
5 env, fmt, panic, 4 env, fmt, panic,
6 time::{Duration, Instant}, 5 time::{Duration, Instant},
7}; 6};
8 7
9use crossbeam_channel::{select, Receiver}; 8use crossbeam_channel::{select, Receiver};
10use lsp_server::{Connection, Notification, Request, Response}; 9use lsp_server::{Connection, Notification, Request, Response};
11use lsp_types::{notification::Notification as _, DidChangeTextDocumentParams}; 10use lsp_types::notification::Notification as _;
12use ra_db::VfsPath; 11use ra_db::VfsPath;
13use ra_ide::{Canceled, FileId}; 12use ra_ide::{Canceled, FileId};
14use ra_prof::profile; 13use 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(&params.text_document.uri) { 423 if let Ok(path) = from_proto::vfs_path(&params.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 }