about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-12 10:21:06 +0000
committerbors <bors@rust-lang.org>2024-08-12 10:21:06 +0000
commit5e753ffe25758a4eeb9e865e599bc86fe778d44a (patch)
treeceeddb7a7ef7d8850f402b89790bda46acf9fe62
parent563dc1cd335360415c3ca532635abba68db9b024 (diff)
parent234d383f5fea762a02a85e20f2282c623ca76739 (diff)
downloadrust-5e753ffe25758a4eeb9e865e599bc86fe778d44a.tar.gz
rust-5e753ffe25758a4eeb9e865e599bc86fe778d44a.zip
Auto merge of #17850 - Veykril:rust-analyzer-crate, r=Veykril
internal: Reply to requests with defaults when vfs is still loading

There is no reason for us to hit the database with queries when we certainly haven't reached a stable state yet. Instead we just reply with default request results until we are in a state where we can do meaningful work. This should save us from wasting resources while starting up at worst, and at best save us from creating query and interning entries that are non-meaningful which ultimately just end up wasting memory.
-rw-r--r--src/tools/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs43
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs41
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md2
5 files changed, 71 insertions, 27 deletions
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index b2cf3451467..561c533a98d 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
 resolver = "2"
 
 [workspace.package]
-rust-version = "1.78"
+rust-version = "1.80"
 edition = "2021"
 license = "MIT OR Apache-2.0"
 authors = ["rust-analyzer team"]
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 ebdc196a658..a105ec63820 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
@@ -97,16 +97,45 @@ impl RequestDispatcher<'_> {
         self
     }
 
-    /// Dispatches a non-latency-sensitive request onto the thread pool.
+    /// Dispatches a non-latency-sensitive request onto the thread pool. When the VFS is marked not
+    /// ready this will return a default constructed [`R::Result`].
     pub(crate) fn on<const ALLOW_RETRYING: bool, R>(
         &mut self,
         f: fn(GlobalStateSnapshot, R::Params) -> anyhow::Result<R::Result>,
     ) -> &mut Self
     where
-        R: lsp_types::request::Request + 'static,
-        R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
-        R::Result: Serialize,
+        R: lsp_types::request::Request<
+                Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
+                Result: Serialize + Default,
+            > + 'static,
+    {
+        if !self.global_state.vfs_done {
+            if let Some(lsp_server::Request { id, .. }) =
+                self.req.take_if(|it| it.method == R::METHOD)
+            {
+                self.global_state.respond(lsp_server::Response::new_ok(id, R::Result::default()));
+            }
+            return self;
+        }
+        self.on_with_thread_intent::<true, ALLOW_RETRYING, R>(ThreadIntent::Worker, f)
+    }
+
+    /// Dispatches a non-latency-sensitive request onto the thread pool. When the VFS is marked not
+    /// ready this will return the parameter as is.
+    pub(crate) fn on_identity<const ALLOW_RETRYING: bool, R, Params>(
+        &mut self,
+        f: fn(GlobalStateSnapshot, Params) -> anyhow::Result<R::Result>,
+    ) -> &mut Self
+    where
+        R: lsp_types::request::Request<Params = Params, Result = Params> + 'static,
+        Params: Serialize + DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
     {
+        if !self.global_state.vfs_done {
+            if let Some((request, params, _)) = self.parse::<R>() {
+                self.global_state.respond(lsp_server::Response::new_ok(request.id, &params))
+            }
+            return self;
+        }
         self.on_with_thread_intent::<true, ALLOW_RETRYING, R>(ThreadIntent::Worker, f)
     }
 
@@ -198,11 +227,7 @@ impl RequestDispatcher<'_> {
         R: lsp_types::request::Request,
         R::Params: DeserializeOwned + fmt::Debug,
     {
-        let req = match &self.req {
-            Some(req) if req.method == R::METHOD => self.req.take()?,
-            _ => return None,
-        };
-
+        let req = self.req.take_if(|it| it.method == R::METHOD)?;
         let res = crate::from_json(R::METHOD, &req.params);
         match res {
             Ok(params) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 1fcb636f856..8d1a686dc4d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -61,7 +61,7 @@ impl Request for FetchDependencyList {
 #[serde(rename_all = "camelCase")]
 pub struct FetchDependencyListParams {}
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Default)]
 #[serde(rename_all = "camelCase")]
 pub struct FetchDependencyListResult {
     pub crates: Vec<CrateInfoResult>,
@@ -194,7 +194,7 @@ pub struct TestItem {
     pub runnable: Option<Runnable>,
 }
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Default)]
 #[serde(rename_all = "camelCase")]
 pub struct DiscoverTestResults {
     pub tests: Vec<TestItem>,
@@ -690,6 +690,12 @@ pub enum ExternalDocsResponse {
     WithLocal(ExternalDocsPair),
 }
 
+impl Default for ExternalDocsResponse {
+    fn default() -> Self {
+        ExternalDocsResponse::Simple(None)
+    }
+}
+
 #[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
 #[serde(rename_all = "camelCase")]
 pub struct ExternalDocsPair {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index e303765aab6..1d4ee71e5c1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -173,8 +173,10 @@ impl GlobalState {
         }
 
         if self.config.discover_workspace_config().is_none() {
-            let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
-            self.fetch_workspaces_queue.request_op("startup".to_owned(), req);
+            self.fetch_workspaces_queue.request_op(
+                "startup".to_owned(),
+                FetchWorkspaceRequest { path: None, force_crate_graph_reload: false },
+            );
             if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
                 self.fetch_workspaces_queue.should_start_op()
             {
@@ -545,6 +547,10 @@ impl GlobalState {
             let snapshot = self.snapshot();
             self.task_pool.handle.spawn_with_sender(ThreadIntent::LatencySensitive, {
                 let subscriptions = subscriptions.clone();
+                // Do not fetch semantic diagnostics (and populate query results) if we haven't even
+                // loaded the initial workspace yet.
+                let fetch_semantic =
+                    self.vfs_done && self.fetch_workspaces_queue.last_op_result().is_some();
                 move |sender| {
                     let diags = fetch_native_diagnostics(
                         &snapshot,
@@ -556,15 +562,19 @@ impl GlobalState {
                         .send(Task::Diagnostics(DiagnosticsTaskKind::Syntax(generation, diags)))
                         .unwrap();
 
-                    let diags = fetch_native_diagnostics(
-                        &snapshot,
-                        subscriptions,
-                        slice,
-                        NativeDiagnosticsFetchKind::Semantic,
-                    );
-                    sender
-                        .send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(generation, diags)))
-                        .unwrap();
+                    if fetch_semantic {
+                        let diags = fetch_native_diagnostics(
+                            &snapshot,
+                            subscriptions,
+                            slice,
+                            NativeDiagnosticsFetchKind::Semantic,
+                        );
+                        sender
+                            .send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(
+                                generation, diags,
+                            )))
+                            .unwrap();
+                    }
                 }
             });
             start = end;
@@ -572,6 +582,9 @@ impl GlobalState {
     }
 
     fn update_tests(&mut self) {
+        if !self.vfs_done {
+            return;
+        }
         let db = self.analysis_host.raw_database();
         let subscriptions = self
             .mem_docs
@@ -1052,9 +1065,9 @@ impl GlobalState {
             .on::<NO_RETRY, lsp_request::GotoImplementation>(handlers::handle_goto_implementation)
             .on::<NO_RETRY, lsp_request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
             .on::<NO_RETRY, lsp_request::InlayHintRequest>(handlers::handle_inlay_hints)
-            .on::<NO_RETRY, lsp_request::InlayHintResolveRequest>(handlers::handle_inlay_hints_resolve)
+            .on_identity::<NO_RETRY, lsp_request::InlayHintResolveRequest, _>(handlers::handle_inlay_hints_resolve)
             .on::<NO_RETRY, lsp_request::CodeLensRequest>(handlers::handle_code_lens)
-            .on::<NO_RETRY, lsp_request::CodeLensResolve>(handlers::handle_code_lens_resolve)
+            .on_identity::<NO_RETRY, lsp_request::CodeLensResolve, _>(handlers::handle_code_lens_resolve)
             .on::<NO_RETRY, lsp_request::PrepareRenameRequest>(handlers::handle_prepare_rename)
             .on::<NO_RETRY, lsp_request::Rename>(handlers::handle_rename)
             .on::<NO_RETRY, lsp_request::References>(handlers::handle_references)
@@ -1081,7 +1094,7 @@ impl GlobalState {
             .on::<NO_RETRY, lsp_ext::Runnables>(handlers::handle_runnables)
             .on::<NO_RETRY, lsp_ext::RelatedTests>(handlers::handle_related_tests)
             .on::<NO_RETRY, lsp_ext::CodeActionRequest>(handlers::handle_code_action)
-            .on::<RETRY, lsp_ext::CodeActionResolveRequest>(handlers::handle_code_action_resolve)
+            .on_identity::<RETRY, lsp_ext::CodeActionResolveRequest, _>(handlers::handle_code_action_resolve)
             .on::<NO_RETRY, lsp_ext::HoverRequest>(handlers::handle_hover)
             .on::<NO_RETRY, lsp_ext::ExternalDocs>(handlers::handle_open_docs)
             .on::<NO_RETRY, lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index e559f88e233..4786bd54d59 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: e92e1f12229b0071
+lsp/ext.rs hash: 3429c08745984b3d
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue: