about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukas@zed.dev>2025-08-07 15:24:39 +0200
committerLukas Wirth <lukas@zed.dev>2025-09-16 09:18:03 +0200
commitfd28cc8a1b2496ac9717d7185a40af123aaefafb (patch)
treed0d354eea70f5aa63bc7c0849eea3eacd5cca4a2
parent9699d357988310919b2af51fce838d3119d45323 (diff)
downloadrust-fd28cc8a1b2496ac9717d7185a40af123aaefafb.tar.gz
rust-fd28cc8a1b2496ac9717d7185a40af123aaefafb.zip
Add more workaround hacks for incorrect startup diagnostics
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs5
4 files changed, 16 insertions, 8 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index 9bcf835b4cc..e80f2953505 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -216,14 +216,14 @@ fn run_server() -> anyhow::Result<()> {
     } = from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;
 
     // lsp-types has a typo in the `/capabilities/workspace/diagnostics` field, its typoed as `diagnostic`
-    if let Some(val) = initialize_params.pointer("/capabilities/workspace/diagnostics") {
-        if let Ok(diag_caps) = from_json::<lsp_types::DiagnosticWorkspaceClientCapabilities>(
+    if let Some(val) = initialize_params.pointer("/capabilities/workspace/diagnostics")
+        && let Ok(diag_caps) = from_json::<lsp_types::DiagnosticWorkspaceClientCapabilities>(
             "DiagnosticWorkspaceClientCapabilities",
             val,
-        ) {
-            tracing::info!("Patching lsp-types workspace diagnostics capabilities: {diag_caps:#?}");
-            capabilities.workspace.get_or_insert_default().diagnostic.get_or_insert(diag_caps);
-        }
+        )
+    {
+        tracing::info!("Patching lsp-types workspace diagnostics capabilities: {diag_caps:#?}");
+        capabilities.workspace.get_or_insert_default().diagnostic.get_or_insert(diag_caps);
     }
 
     let root_path = match root_uri
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 2f1afba3634..89d6fb8edc2 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -183,6 +183,10 @@ pub(crate) struct GlobalState {
     /// this queue should run only *after* [`GlobalState::process_changes`] has
     /// been called.
     pub(crate) deferred_task_queue: TaskQueue,
+    /// HACK: Workaround for https://github.com/rust-lang/rust-analyzer/issues/19709
+    /// This is marked true if we failed to load a crate root file at crate graph creation,
+    /// which will usually end up causing a bunch of incorrect diagnostics on startup.
+    pub(crate) incomplete_crate_graph: bool,
 }
 
 /// An immutable snapshot of the world's state at a point in time.
@@ -298,6 +302,7 @@ impl GlobalState {
             discover_workspace_queue: OpQueue::default(),
 
             deferred_task_queue: task_queue,
+            incomplete_crate_graph: false,
         };
         // Apply any required database inputs from the config.
         this.update_configuration(config);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
index b25245dd884..10bbb0bb31d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -141,7 +141,7 @@ impl RequestDispatcher<'_> {
                 Result: Serialize,
             > + 'static,
     {
-        if !self.global_state.vfs_done {
+        if !self.global_state.vfs_done || self.global_state.incomplete_crate_graph {
             if let Some(lsp_server::Request { id, .. }) =
                 self.req.take_if(|it| it.method == R::METHOD)
             {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index a8a54930c6e..c15496b3f6c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -741,13 +741,16 @@ impl GlobalState {
             })
             .collect();
 
+        self.incomplete_crate_graph = false;
         let (crate_graph, proc_macro_paths) = {
             // Create crate graph from all the workspaces
             let vfs = &self.vfs.read().0;
             let load = |path: &AbsPath| {
                 let vfs_path = vfs::VfsPath::from(path.to_path_buf());
                 self.crate_graph_file_dependencies.insert(vfs_path.clone());
-                vfs.file_id(&vfs_path).and_then(|(file_id, excluded)| {
+                let file_id = vfs.file_id(&vfs_path);
+                self.incomplete_crate_graph |= file_id.is_none();
+                file_id.and_then(|(file_id, excluded)| {
                     (excluded == vfs::FileExcluded::No).then_some(file_id)
                 })
             };