diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 2d9ddd76d8..c09f27bfe3 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -730,6 +730,9 @@ impl Buffer { let version = version.map(|version| version as usize); let content = if let Some(version) = version { let language_server = self.language_server.as_mut().unwrap(); + language_server + .pending_snapshots + .retain(|&v, _| v >= version); let snapshot = language_server .pending_snapshots .get(&version) @@ -756,6 +759,10 @@ impl Buffer { let entry = &mut diagnostics[ix]; let mut start = entry.range.start; let mut end = entry.range.end; + + // Some diagnostics are based on files on disk instead of buffers' + // current contents. Adjust these diagnostics' ranges to reflect + // any unsaved edits. if entry .diagnostic .source @@ -781,6 +788,8 @@ impl Buffer { entry.range = content.clip_point_utf16(start, Bias::Left) ..content.clip_point_utf16(end, Bias::Right); + + // Expand empty ranges by one character if entry.range.start == entry.range.end { entry.range.end.column += 1; entry.range.end = content.clip_point_utf16(entry.range.end, Bias::Right); @@ -794,19 +803,6 @@ impl Buffer { drop(edits_since_save); self.diagnostics = DiagnosticSet::new(diagnostics, content); - - if let Some(version) = version { - let language_server = self.language_server.as_mut().unwrap(); - let versions_to_delete = language_server - .pending_snapshots - .range(..version) - .map(|(v, _)| *v) - .collect::>(); - for version in versions_to_delete { - language_server.pending_snapshots.remove(&version); - } - } - self.diagnostics_update_count += 1; cx.notify(); cx.emit(Event::DiagnosticsUpdated); diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 99161d1f5c..317a6ed84a 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -9,10 +9,9 @@ use anyhow::{anyhow, Result}; pub use buffer::Operation; pub use buffer::*; pub use diagnostic_set::DiagnosticEntry; -use gpui::{executor::Background, AppContext}; +use gpui::AppContext; use highlight_map::HighlightMap; use lazy_static::lazy_static; -use lsp::LanguageServer; use parking_lot::Mutex; use serde::Deserialize; use std::{collections::HashSet, path::Path, str, sync::Arc}; @@ -48,7 +47,7 @@ pub struct LanguageServerConfig { pub disk_based_diagnostic_sources: HashSet, #[cfg(any(test, feature = "test-support"))] #[serde(skip)] - pub fake_server: Option<(Arc, Arc)>, + pub fake_server: Option<(Arc, Arc)>, } #[derive(Clone, Debug, Deserialize)] @@ -219,7 +218,9 @@ impl Grammar { #[cfg(any(test, feature = "test-support"))] impl LanguageServerConfig { - pub async fn fake(executor: Arc) -> (Self, lsp::FakeLanguageServer) { + pub async fn fake( + executor: Arc, + ) -> (Self, lsp::FakeLanguageServer) { let (server, fake) = lsp::LanguageServer::fake(executor).await; fake.started .store(false, std::sync::atomic::Ordering::SeqCst);