Skip to content

Commit bc9fab1

Browse files
bors[bot]lnicola
andauthored
Merge #5532
5532: Restore line index optimization for edits r=matklad a=lnicola Co-authored-by: Laurențiu Nicola <[email protected]>
2 parents edcd0b1 + 83a87fc commit bc9fab1

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed

crates/rust-analyzer/src/lsp_utils.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Utilities for LSP-related boilerplate code.
2-
use std::{error::Error, ops::Range};
2+
use std::{borrow::Cow, error::Error, ops::Range};
33

44
use lsp_server::Notification;
55
use ra_db::Canceled;
@@ -84,8 +84,8 @@ impl GlobalState {
8484
pub(crate) fn apply_document_changes(
8585
old_text: &mut String,
8686
content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
87+
mut line_index: Cow<'_, LineIndex>,
8788
) {
88-
let mut line_index = LineIndex::new(old_text);
8989
// The changes we got must be applied sequentially, but can cross lines so we
9090
// have to keep our line index updated.
9191
// Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we
@@ -110,7 +110,7 @@ pub(crate) fn apply_document_changes(
110110
match change.range {
111111
Some(range) => {
112112
if !index_valid.covers(range.end.line) {
113-
line_index = LineIndex::new(&old_text);
113+
line_index = Cow::Owned(LineIndex::new(old_text));
114114
}
115115
index_valid = IndexValid::UpToLineExclusive(range.start.line);
116116
let range = from_proto::text_range(&line_index, range);
@@ -145,10 +145,15 @@ mod tests {
145145
};
146146
}
147147

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+
148153
let mut text = String::new();
149-
apply_document_changes(&mut text, vec![]);
154+
run(&mut text, vec![]);
150155
assert_eq!(text, "");
151-
apply_document_changes(
156+
run(
152157
&mut text,
153158
vec![TextDocumentContentChangeEvent {
154159
range: None,
@@ -157,39 +162,36 @@ mod tests {
157162
}],
158163
);
159164
assert_eq!(text, "the");
160-
apply_document_changes(&mut text, c![0, 3; 0, 3 => " quick"]);
165+
run(&mut text, c![0, 3; 0, 3 => " quick"]);
161166
assert_eq!(text, "the quick");
162-
apply_document_changes(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
167+
run(&mut text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
163168
assert_eq!(text, "quick foxes");
164-
apply_document_changes(&mut text, c![0, 11; 0, 11 => "\ndream"]);
169+
run(&mut text, c![0, 11; 0, 11 => "\ndream"]);
165170
assert_eq!(text, "quick foxes\ndream");
166-
apply_document_changes(&mut text, c![1, 0; 1, 0 => "have "]);
171+
run(&mut text, c![1, 0; 1, 0 => "have "]);
167172
assert_eq!(text, "quick foxes\nhave dream");
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-
);
173+
run(&mut text, c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"]);
172174
assert_eq!(text, "the quick foxes\nhave quiet dreams\n");
173-
apply_document_changes(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]);
175+
run(&mut text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]);
174176
assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n");
175-
apply_document_changes(
177+
run(
176178
&mut text,
177179
c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"],
178180
);
179181
assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n");
180-
apply_document_changes(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
182+
run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
181183
assert_eq!(text, "the quick \nthey have quiet dreams\n");
182184

183185
text = String::from("❤️");
184-
apply_document_changes(&mut text, c![0, 0; 0, 0 => "a"]);
186+
run(&mut text, c![0, 0; 0, 0 => "a"]);
185187
assert_eq!(text, "a❤️");
186188

187189
text = String::from("a\nb");
188-
apply_document_changes(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
190+
run(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
189191
assert_eq!(text, "adcb");
190192

191193
text = String::from("a\nb");
192-
apply_document_changes(&mut text, c![0, 1; 1, 0 => \nc", 0, 2; 0, 2 => "c"]);
194+
run(&mut text, c![0, 1; 1, 0 => \nc", 0, 2; 0, 2 => "c"]);
193195
assert_eq!(text, "ațc\ncb");
194196
}
195197
}

crates/rust-analyzer/src/main_loop.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
//! The main loop of `rust-analyzer` responsible for dispatching LSP
22
//! requests/replies and notifications back to the client.
33
use std::{
4+
borrow::Cow,
45
env, fmt, panic,
56
time::{Duration, Instant},
67
};
78

89
use crossbeam_channel::{select, Receiver};
910
use lsp_server::{Connection, Notification, Request, Response};
10-
use lsp_types::notification::Notification as _;
11+
use lsp_types::{notification::Notification as _, DidChangeTextDocumentParams};
1112
use ra_db::VfsPath;
1213
use ra_ide::{Canceled, FileId};
1314
use ra_prof::profile;
@@ -421,15 +422,20 @@ impl GlobalState {
421422
})?
422423
.on::<lsp_types::notification::DidChangeTextDocument>(|this, params| {
423424
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
424-
let doc = this.mem_docs.get_mut(&path).unwrap();
425+
let DidChangeTextDocumentParams { text_document, content_changes } = params;
425426
let vfs = &mut this.vfs.write().0;
427+
let world = this.snapshot();
426428
let file_id = vfs.file_id(&path).unwrap();
429+
430+
// let file_id = vfs.file_id(&path).unwrap();
427431
let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap();
428-
apply_document_changes(&mut text, params.content_changes);
432+
let line_index = world.analysis.file_line_index(file_id)?;
433+
apply_document_changes(&mut text, content_changes, Cow::Borrowed(&line_index));
429434

430435
// The version passed in DidChangeTextDocument is the version after all edits are applied
431436
// so we should apply it before the vfs is notified.
432-
doc.version = params.text_document.version;
437+
let doc = this.mem_docs.get_mut(&path).unwrap();
438+
doc.version = text_document.version;
433439

434440
vfs.set_file_contents(path.clone(), Some(text.into_bytes()));
435441
}

0 commit comments

Comments
 (0)