Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17886 - Wilfred:prime_caches_quiescent, r=Veykril
internal: 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.
bors 2024-08-20
parent 6446173 · parent 0edb0e1 · commit 979e3b5
-rw-r--r--crates/rust-analyzer/src/reload.rs23
1 files 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()
{