Unnamed repository; edit this file 'description' to name the repository.
minor: Simplify implementation of apply_document_changes
While reading through the code base, I stumbled across a piece of code that I found hard to read despite its simple purpose. This is my attempt at making the code easier to understand for future readers. I won't be offended if this is too minor and not worth your time.
Martin Huschenbett 2023-12-31
parent e1e4626 · commit b9933fd
-rw-r--r--crates/rust-analyzer/src/lsp/utils.rs35
1 files changed, 12 insertions, 23 deletions
diff --git a/crates/rust-analyzer/src/lsp/utils.rs b/crates/rust-analyzer/src/lsp/utils.rs
index b388b31759..a4417e4d4a 100644
--- a/crates/rust-analyzer/src/lsp/utils.rs
+++ b/crates/rust-analyzer/src/lsp/utils.rs
@@ -171,30 +171,19 @@ pub(crate) fn apply_document_changes(
file_contents: impl FnOnce() -> String,
mut content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
) -> String {
- // Skip to the last full document change, as it invalidates all previous changes anyways.
- let mut start = content_changes
- .iter()
- .rev()
- .position(|change| change.range.is_none())
- .map(|idx| content_changes.len() - idx - 1)
- .unwrap_or(0);
-
- let mut text: String = match content_changes.get_mut(start) {
- // peek at the first content change as an optimization
- Some(lsp_types::TextDocumentContentChangeEvent { range: None, text, .. }) => {
- let text = mem::take(text);
- start += 1;
-
- // The only change is a full document update
- if start == content_changes.len() {
- return text;
+ // If at least one of the changes is a full document change, use the last
+ // of them as the starting point and ignore all previous changes.
+ let (mut text, content_changes) =
+ match content_changes.iter().rposition(|change| change.range.is_none()) {
+ Some(idx) => {
+ let text = mem::take(&mut content_changes[idx].text);
+ (text, &content_changes[idx + 1..])
}
- text
- }
- Some(_) => file_contents(),
- // we received no content changes
- None => return file_contents(),
- };
+ None => (file_contents(), &content_changes[..]),
+ };
+ if content_changes.is_empty() {
+ return text;
+ }
let mut line_index = LineIndex {
// the index will be overwritten in the bottom loop's first iteration