about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-02-08 09:43:16 +0000
committerbors <bors@rust-lang.org>2024-02-08 09:43:16 +0000
commitae89522928a93d8a7f64ebe4a485ca7d088c2829 (patch)
tree5582b1ab7ab637ab094a1edd108d0f83e45fd8bf
parentbcc8a09a0db8428f12b557b164809d387f02845d (diff)
parent0258f60cfeb2a3355dd050fce9ed51b55d8cb613 (diff)
downloadrust-ae89522928a93d8a7f64ebe4a485ca7d088c2829.tar.gz
rust-ae89522928a93d8a7f64ebe4a485ca7d088c2829.zip
Auto merge of #16510 - Veykril:single-package-check, r=Veykril
feat: Allow cargo check to run on only the current package

cc https://github.com/rust-lang/rust-analyzer/pull/13336, https://github.com/rust-lang/rust-analyzer/issues/12882
-rw-r--r--crates/flycheck/src/lib.rs25
-rw-r--r--crates/rust-analyzer/src/config.rs7
-rw-r--r--crates/rust-analyzer/src/handlers/notification.rs49
-rw-r--r--crates/rust-analyzer/src/main_loop.rs2
-rw-r--r--crates/rust-analyzer/src/reload.rs2
-rw-r--r--docs/user/generated_config.adoc6
-rw-r--r--editors/code/package.json5
7 files changed, 68 insertions, 28 deletions
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index ef1404487e6..c59aff2a8bb 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -100,9 +100,14 @@ impl FlycheckHandle {
         FlycheckHandle { id, sender, _thread: thread }
     }
 
-    /// Schedule a re-start of the cargo check worker.
-    pub fn restart(&self) {
-        self.sender.send(StateChange::Restart).unwrap();
+    /// Schedule a re-start of the cargo check worker to do a workspace wide check.
+    pub fn restart_workspace(&self) {
+        self.sender.send(StateChange::Restart(None)).unwrap();
+    }
+
+    /// Schedule a re-start of the cargo check worker to do a package wide check.
+    pub fn restart_for_package(&self, package: String) {
+        self.sender.send(StateChange::Restart(Some(package))).unwrap();
     }
 
     /// Stop this cargo check worker.
@@ -153,7 +158,7 @@ pub enum Progress {
 }
 
 enum StateChange {
-    Restart,
+    Restart(Option<String>),
     Cancel,
 }
 
@@ -213,7 +218,7 @@ impl FlycheckActor {
                     tracing::debug!(flycheck_id = self.id, "flycheck cancelled");
                     self.cancel_check_process();
                 }
-                Event::RequestStateChange(StateChange::Restart) => {
+                Event::RequestStateChange(StateChange::Restart(package)) => {
                     // Cancel the previously spawned process
                     self.cancel_check_process();
                     while let Ok(restart) = inbox.recv_timeout(Duration::from_millis(50)) {
@@ -223,7 +228,7 @@ impl FlycheckActor {
                         }
                     }
 
-                    let command = self.check_command();
+                    let command = self.check_command(package.as_deref());
                     let formatted_command = format!("{:?}", command);
 
                     tracing::debug!(?command, "will restart flycheck");
@@ -297,7 +302,7 @@ impl FlycheckActor {
         }
     }
 
-    fn check_command(&self) -> Command {
+    fn check_command(&self, package: Option<&str>) -> Command {
         let (mut cmd, args) = match &self.config {
             FlycheckConfig::CargoCommand {
                 command,
@@ -314,7 +319,11 @@ impl FlycheckActor {
                 let mut cmd = Command::new(toolchain::cargo());
                 cmd.arg(command);
                 cmd.current_dir(&self.root);
-                cmd.arg("--workspace");
+
+                match package {
+                    Some(pkg) => cmd.arg("-p").arg(pkg),
+                    None => cmd.arg("--workspace"),
+                };
 
                 cmd.arg(if *ansi_color_output {
                     "--message-format=json-diagnostic-rendered-ansi"
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 815f6ea12e8..ff81c4dc5aa 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -223,6 +223,9 @@ config_data! {
         ///
         /// Aliased as `"checkOnSave.targets"`.
         check_targets | checkOnSave_targets | checkOnSave_target: Option<CheckOnSaveTargets> = "null",
+        /// Whether `--workspace` should be passed to `cargo check`.
+        /// If false, `-p <package>` will be passed instead.
+        check_workspace: bool = "true",
 
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -1323,6 +1326,10 @@ impl Config {
         }
     }
 
+    pub fn flycheck_workspace(&self) -> bool {
+        self.data.check_workspace
+    }
+
     pub fn flycheck(&self) -> FlycheckConfig {
         match &self.data.check_overrideCommand {
             Some(args) if !args.is_empty() => {
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index 1f24e950105..268fe00979b 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -160,7 +160,7 @@ pub(crate) fn handle_did_save_text_document(
     } else if state.config.check_on_save() {
         // No specific flycheck was triggered, so let's trigger all of them.
         for flycheck in state.flycheck.iter() {
-            flycheck.restart();
+            flycheck.restart_workspace();
         }
     }
     Ok(())
@@ -281,27 +281,40 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
             let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
 
             // Find all workspaces that have at least one target containing the saved file
-            let workspace_ids = world.workspaces.iter().enumerate().filter(|(_, ws)| match ws {
-                project_model::ProjectWorkspace::Cargo { cargo, .. } => {
-                    cargo.packages().any(|pkg| {
-                        cargo[pkg]
-                            .targets
-                            .iter()
-                            .any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()))
-                    })
-                }
-                project_model::ProjectWorkspace::Json { project, .. } => {
-                    project.crates().any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c))
-                }
-                project_model::ProjectWorkspace::DetachedFiles { .. } => false,
+            let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
+                let package = match ws {
+                    project_model::ProjectWorkspace::Cargo { cargo, .. } => {
+                        cargo.packages().find_map(|pkg| {
+                            let has_target_with_root = cargo[pkg]
+                                .targets
+                                .iter()
+                                .any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
+                            has_target_with_root.then(|| cargo[pkg].name.clone())
+                        })
+                    }
+                    project_model::ProjectWorkspace::Json { project, .. } => {
+                        if !project
+                            .crates()
+                            .any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c))
+                        {
+                            return None;
+                        }
+                        None
+                    }
+                    project_model::ProjectWorkspace::DetachedFiles { .. } => return None,
+                };
+                Some((idx, package))
             });
 
             // Find and trigger corresponding flychecks
             for flycheck in world.flycheck.iter() {
-                for (id, _) in workspace_ids.clone() {
+                for (id, package) in workspace_ids.clone() {
                     if id == flycheck.id() {
                         updated = true;
-                        flycheck.restart();
+                        match package.filter(|_| !world.config.flycheck_workspace()) {
+                            Some(package) => flycheck.restart_for_package(package),
+                            None => flycheck.restart_workspace(),
+                        }
                         continue;
                     }
                 }
@@ -309,7 +322,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
             // No specific flycheck was triggered, so let's trigger all of them.
             if !updated {
                 for flycheck in world.flycheck.iter() {
-                    flycheck.restart();
+                    flycheck.restart_workspace();
                 }
             }
             Ok(())
@@ -351,7 +364,7 @@ pub(crate) fn handle_run_flycheck(
     }
     // No specific flycheck was triggered, so let's trigger all of them.
     for flycheck in state.flycheck.iter() {
-        flycheck.restart();
+        flycheck.restart_workspace();
     }
     Ok(())
 }
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index f3ead6d04f7..dc15a4c0a44 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -314,7 +314,7 @@ impl GlobalState {
             if became_quiescent {
                 if self.config.check_on_save() {
                     // Project has loaded properly, kick off initial flycheck
-                    self.flycheck.iter().for_each(FlycheckHandle::restart);
+                    self.flycheck.iter().for_each(FlycheckHandle::restart_workspace);
                 }
                 if self.config.prefill_caches() {
                     self.prime_caches_queue.request_op("became quiescent".to_string(), ());
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 65c00cc08d1..2a0478d62f5 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -503,7 +503,7 @@ impl GlobalState {
             let mut crate_graph_file_dependencies = FxHashSet::default();
 
             let mut load = |path: &AbsPath| {
-                let _p = tracing::span!(tracing::Level::INFO, "switch_workspaces::load").entered();
+                let _p = tracing::span!(tracing::Level::DEBUG, "switch_workspaces::load").entered();
                 let vfs_path = vfs::VfsPath::from(path.to_path_buf());
                 crate_graph_file_dependencies.insert(vfs_path.clone());
                 match vfs.file_id(&vfs_path) {
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index cfa7503d739..3ff2229346f 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -251,6 +251,12 @@ Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets,
 
 Aliased as `"checkOnSave.targets"`.
 --
+[[rust-analyzer.check.workspace]]rust-analyzer.check.workspace (default: `true`)::
++
+--
+Whether `--workspace` should be passed to `cargo check`.
+If false, `-p <package>` will be passed instead.
+--
 [[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index 841e364ed84..7ad5a3abbc9 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -803,6 +803,11 @@
                         }
                     ]
                 },
+                "rust-analyzer.check.workspace": {
+                    "markdownDescription": "Whether `--workspace` should be passed to `cargo check`.\nIf false, `-p <package>` will be passed instead.",
+                    "default": true,
+                    "type": "boolean"
+                },
                 "rust-analyzer.completion.autoimport.enable": {
                     "markdownDescription": "Toggles the additional completions that automatically add imports when completed.\nNote that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
                     "default": true,