From 0edb0e1e6284cff16aaa016768b801a0eec82322 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 13 Aug 2024 16:26:37 -0700 Subject: [PATCH] ServerStatusParams should consider 'prime caches' in quiescent status Priming caches is a performance win, but it takes a lock on the salsa database and prevents rust-analyzer from responding to e.g. go-to-def requests. This causes confusion for users, who see the spinner next to rust-analyzer in the VS Code footer stop, so they start attempting to navigate their code. Instead, set the `quiescent` status in LSP to false during cache priming, so the VS Code spinner persists until we can respond to any LSP request. --- crates/rust-analyzer/src/reload.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 510dc22603..884a8e8347 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -61,6 +61,10 @@ pub(crate) enum ProcMacroProgress { } impl GlobalState { + /// Is the server quiescent? + /// + /// This indicates that we've fully loaded the projects and + /// are ready to do semantic work. pub(crate) fn is_quiescent(&self) -> bool { self.vfs_done && self.last_reported_status.is_some() @@ -71,6 +75,15 @@ impl GlobalState { && self.vfs_progress_config_version >= self.vfs_config_version } + /// Is the server ready to respond to analysis dependent LSP requests? + /// + /// Unlike `is_quiescent`, this returns false when we're indexing + /// the project, because we're holding the salsa lock and cannot + /// respond to LSP requests that depend on salsa data. + fn is_fully_ready(&self) -> bool { + self.is_quiescent() && !self.prime_caches_queue.op_in_progress() + } + pub(crate) fn update_configuration(&mut self, config: Config) { let _p = tracing::info_span!("GlobalState::update_configuration").entered(); let old_config = mem::replace(&mut self.config, Arc::new(config)); @@ -102,13 +115,15 @@ impl GlobalState { } pub(crate) fn current_status(&self) -> lsp_ext::ServerStatusParams { - let quiescent = self.is_quiescent(); - let mut status = - lsp_ext::ServerStatusParams { health: lsp_ext::Health::Ok, quiescent, message: None }; + let mut status = lsp_ext::ServerStatusParams { + health: lsp_ext::Health::Ok, + quiescent: self.is_fully_ready(), + message: None, + }; let mut message = String::new(); if !self.config.cargo_autoreload(None) - && quiescent + && self.is_quiescent() && self.fetch_workspaces_queue.op_requested() && self.config.discover_workspace_config().is_none() {