From 7a35ea7b2579b4ff0fa7f7349369e3d4bc760b8e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 7 Feb 2022 16:29:05 +0100 Subject: [PATCH] Tolerate language servers reporting non-monotonic buffer versions This isn't perfect but we'll retain up to 10 old versions just in case there are race conditions in the language server. We haven't seen this in the wild but we're concerned about diagnostic reporting racing with code action resolution. Co-Authored-By: Nathan Sobo --- crates/language/src/buffer.rs | 23 +++++++++++++++-------- crates/project/src/project.rs | 5 +---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index c626a78f90..df6896cd46 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1025,14 +1025,7 @@ impl Buffer { let version = version.map(|version| version as usize); let content = if let Some((version, language_server)) = version.zip(self.language_server.as_mut()) { - language_server - .pending_snapshots - .retain(|&v, _| v >= version); - let snapshot = language_server - .pending_snapshots - .get(&version) - .ok_or_else(|| anyhow!("missing snapshot"))?; - &snapshot.buffer_snapshot + language_server.snapshot_for_version(version)? } else { self.deref() }; @@ -2772,6 +2765,20 @@ impl operation_queue::Operation for Operation { } } +impl LanguageServerState { + fn snapshot_for_version(&mut self, version: usize) -> Result<&text::BufferSnapshot> { + const OLD_VERSIONS_TO_RETAIN: usize = 10; + + self.pending_snapshots + .retain(|&v, _| v + OLD_VERSIONS_TO_RETAIN >= version); + let snapshot = self + .pending_snapshots + .get(&version) + .ok_or_else(|| anyhow!("missing snapshot"))?; + Ok(&snapshot.buffer_snapshot) + } +} + impl Default for Diagnostic { fn default() -> Self { Self { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 378a126311..01c18ae023 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1241,10 +1241,7 @@ impl Project { lsp::DocumentChangeOperation::Edit(edit) => todo!(), } } - // match edit { - // Ok(edit) => edit., - // Err(_) => todo!(), - // } + Ok(Default::default()) }) } else {