From a762baca028e2a6f5efeb7d7804de08d035ba0c5 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Mon, 17 Oct 2022 17:53:50 +0200
Subject: [PATCH] fix: Fix formatting requests hanging when r-a is still
 starting

The reason for that was that we were calculating the crate defmaps
of the file we are saving by accident causing us to get stuck waiting
on their expensive computation, while we only need the relevant crate
id.
---
 crates/ide/src/lib.rs                         |  4 ++--
 crates/ide/src/parent_module.rs               | 12 +++++-------
 crates/ide/src/status.rs                      |  2 +-
 crates/rust-analyzer/src/cargo_target_spec.rs |  6 +-----
 crates/rust-analyzer/src/dispatch.rs          |  4 ++--
 crates/rust-analyzer/src/global_state.rs      |  7 +++----
 crates/rust-analyzer/src/handlers.rs          |  4 ++--
 crates/rust-analyzer/src/main_loop.rs         |  2 +-
 8 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 77fe0dbf55..09a5cb03ec 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -482,8 +482,8 @@ impl Analysis {
     }
 
     /// Returns crates this file belongs too.
-    pub fn crate_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
-        self.with_db(|db| parent_module::crate_for(db, file_id))
+    pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
+        self.with_db(|db| parent_module::crates_for(db, file_id))
     }
 
     /// Returns the edition of the given crate.
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index 8f3cc86873..9d425954e3 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -1,9 +1,8 @@
 use hir::Semantics;
 use ide_db::{
-    base_db::{CrateId, FileId, FilePosition},
+    base_db::{CrateId, FileId, FileLoader, FilePosition},
     RootDatabase,
 };
-use itertools::Itertools;
 use syntax::{
     algo::find_node_at_offset,
     ast::{self, AstNode},
@@ -55,9 +54,8 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
 }
 
 /// Returns `Vec` for the same reason as `parent_module`
-pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
-    let sema = Semantics::new(db);
-    sema.to_module_defs(file_id).map(|module| module.krate().into()).unique().collect()
+pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
+    db.relevant_crates(file_id).iter().copied().collect()
 }
 
 #[cfg(test)]
@@ -147,7 +145,7 @@ $0
 mod foo;
 "#,
         );
-        assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1);
+        assert_eq!(analysis.crates_for(file_id).unwrap().len(), 1);
     }
 
     #[test]
@@ -162,6 +160,6 @@ mod baz;
 mod baz;
 "#,
         );
-        assert_eq!(analysis.crate_for(file_id).unwrap().len(), 2);
+        assert_eq!(analysis.crates_for(file_id).unwrap().len(), 2);
     }
 }
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index f4d0387440..20810c25b3 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -45,7 +45,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
 
     if let Some(file_id) = file_id {
         format_to!(buf, "\nFile info:\n");
-        let crates = crate::parent_module::crate_for(db, file_id);
+        let crates = crate::parent_module::crates_for(db, file_id);
         if crates.is_empty() {
             format_to!(buf, "Does not belong to any crate");
         }
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index e1675a030c..cbde735476 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -118,11 +118,7 @@ impl CargoTargetSpec {
         global_state_snapshot: &GlobalStateSnapshot,
         file_id: FileId,
     ) -> Result<Option<CargoTargetSpec>> {
-        let crate_id = match &*global_state_snapshot.analysis.crate_for(file_id)? {
-            &[crate_id, ..] => crate_id,
-            _ => return Ok(None),
-        };
-        let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_crate_root(crate_id) {
+        let (cargo_ws, target) = match global_state_snapshot.cargo_target_for_file_id(file_id) {
             Some(it) => it,
             None => return Ok(None),
         };
diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs
index f16559148e..57899b5991 100644
--- a/crates/rust-analyzer/src/dispatch.rs
+++ b/crates/rust-analyzer/src/dispatch.rs
@@ -52,7 +52,7 @@ impl<'a> RequestDispatcher<'a> {
             let _pctx = stdx::panic_context::enter(panic_context);
             f(self.global_state, params)
         };
-        if let Ok(response) = result_to_response::<R>(req.id.clone(), result) {
+        if let Ok(response) = result_to_response::<R>(req.id, result) {
             self.global_state.respond(response);
         }
 
@@ -80,7 +80,7 @@ impl<'a> RequestDispatcher<'a> {
             f(global_state_snapshot, params)
         });
 
-        if let Ok(response) = thread_result_to_response::<R>(req.id.clone(), result) {
+        if let Ok(response) = thread_result_to_response::<R>(req.id, result) {
             self.global_state.respond(response);
         }
 
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 000ff88e45..4cddb12083 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant};
 use crossbeam_channel::{unbounded, Receiver, Sender};
 use flycheck::FlycheckHandle;
 use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId};
-use ide_db::base_db::{CrateId, FileLoader, SourceDatabase};
+use ide_db::base_db::{FileLoader, SourceDatabase};
 use lsp_types::{SemanticTokens, Url};
 use parking_lot::{Mutex, RwLock};
 use proc_macro_api::ProcMacroServer;
@@ -398,11 +398,10 @@ impl GlobalStateSnapshot {
         url_from_abs_path(path)
     }
 
-    pub(crate) fn cargo_target_for_crate_root(
+    pub(crate) fn cargo_target_for_file_id(
         &self,
-        crate_id: CrateId,
+        file_id: FileId,
     ) -> Option<(&CargoWorkspace, Target)> {
-        let file_id = self.analysis.crate_root(crate_id).ok()?;
         let path = self.vfs.read().0.file_path(file_id);
         let path = path.as_path()?;
         self.workspaces.iter().find_map(|ws| match ws {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 8c3ea77d06..701a009ea8 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -658,7 +658,7 @@ pub(crate) fn handle_parent_module(
 
         // check if invoked at the crate root
         let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
-        let crate_id = match snap.analysis.crate_for(file_id)?.first() {
+        let crate_id = match snap.analysis.crates_for(file_id)?.first() {
             Some(&crate_id) => crate_id,
             None => return Ok(None),
         };
@@ -1782,7 +1782,7 @@ fn run_rustfmt(
 ) -> Result<Option<Vec<lsp_types::TextEdit>>> {
     let file_id = from_proto::file_id(snap, &text_document.uri)?;
     let file = snap.analysis.file_text(file_id)?;
-    let crate_ids = snap.analysis.crate_for(file_id)?;
+    let crate_ids = snap.analysis.crates_for(file_id)?;
 
     let line_index = snap.file_line_index(file_id)?;
 
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 15922dac65..7cd7d00248 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -767,7 +767,7 @@ impl GlobalState {
                         let analysis = this.analysis_host.analysis();
                         // Crates containing or depending on the saved file
                         let crate_ids: Vec<_> = analysis
-                            .crate_for(file_id)?
+                            .crates_for(file_id)?
                             .into_iter()
                             .flat_map(|id| {
                                 this.analysis_host