Merge pull request #2179 from zed-industries/debounce-diagnostics

Simulate disk-based diagnostics finishing 1s after saving buffer
This commit is contained in:
Antonio Scandurra
2023-02-16 16:34:19 +01:00
committed by GitHub
+54 -25
View File
@@ -59,7 +59,7 @@ use std::{
atomic::{AtomicUsize, Ordering::SeqCst},
Arc,
},
time::Instant,
time::{Duration, Instant},
};
use terminal::{Terminal, TerminalBuilder};
use util::{debug_panic, defer, post_inc, ResultExt, TryFutureExt as _};
@@ -185,6 +185,7 @@ pub enum LanguageServerState {
language: Arc<Language>,
adapter: Arc<CachedLspAdapter>,
server: Arc<LanguageServer>,
simulate_disk_based_diagnostics_completion: Option<Task<()>>,
},
}
@@ -1716,19 +1717,39 @@ impl Project {
.log_err();
}
// After saving a buffer, simulate disk-based diagnostics being finished for languages
// that don't support a disk-based progress token.
let (lsp_adapter, language_server) =
self.language_server_for_buffer(buffer.read(cx), cx)?;
if lsp_adapter.disk_based_diagnostics_progress_token.is_none() {
let server_id = language_server.server_id();
self.disk_based_diagnostics_finished(server_id, cx);
self.broadcast_language_server_update(
server_id,
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
proto::LspDiskBasedDiagnosticsUpdated {},
),
);
let language_server_id = self.language_server_id_for_buffer(buffer.read(cx), cx)?;
if let Some(LanguageServerState::Running {
adapter,
simulate_disk_based_diagnostics_completion,
..
}) = self.language_servers.get_mut(&language_server_id)
{
// After saving a buffer using a language server that doesn't provide
// a disk-based progress token, kick off a timer that will reset every
// time the buffer is saved. If the timer eventually fires, simulate
// disk-based diagnostics being finished so that other pieces of UI
// (e.g., project diagnostics view, diagnostic status bar) can update.
// We don't emit an event right away because the language server might take
// some time to publish diagnostics.
if adapter.disk_based_diagnostics_progress_token.is_none() {
const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
let task = cx.spawn_weak(|this, mut cx| async move {
cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await;
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx | {
this.disk_based_diagnostics_finished(language_server_id, cx);
this.broadcast_language_server_update(
language_server_id,
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
proto::LspDiskBasedDiagnosticsUpdated {},
),
);
});
}
});
*simulate_disk_based_diagnostics_completion = Some(task);
}
}
}
_ => {}
@@ -1749,6 +1770,7 @@ impl Project {
adapter,
language,
server,
..
}) = self.language_servers.get(id)
{
return Some((adapter, language, server));
@@ -2035,6 +2057,7 @@ impl Project {
adapter: adapter.clone(),
language,
server: language_server.clone(),
simulate_disk_based_diagnostics_completion: None,
},
);
this.language_server_statuses.insert(
@@ -3105,6 +3128,7 @@ impl Project {
adapter,
language,
server,
..
}) = self.language_servers.get(server_id)
{
let adapter = adapter.clone();
@@ -6178,22 +6202,27 @@ impl Project {
buffer: &Buffer,
cx: &AppContext,
) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
let server_id = self.language_server_id_for_buffer(buffer, cx)?;
let server = self.language_servers.get(&server_id)?;
if let LanguageServerState::Running {
adapter, server, ..
} = server
{
Some((adapter, server))
} else {
None
}
}
fn language_server_id_for_buffer(&self, buffer: &Buffer, cx: &AppContext) -> Option<usize> {
if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
let name = language.lsp_adapter()?.name.clone();
let worktree_id = file.worktree_id(cx);
let key = (worktree_id, name);
if let Some(server_id) = self.language_server_ids.get(&key) {
if let Some(LanguageServerState::Running {
adapter, server, ..
}) = self.language_servers.get(server_id)
{
return Some((adapter, server));
}
}
self.language_server_ids.get(&key).copied()
} else {
None
}
None
}
}