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.
This commit is contained in:
bors 2024-08-19 17:30:25 +00:00
commit 979e3b54f7

View file

@ -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()
{