Skip to content

Commit 0258f60

Browse files
committed
feat: Allow cargo check to run on only the current package
1 parent bcc8a09 commit 0258f60

File tree

7 files changed

+68
-28
lines changed

7 files changed

+68
-28
lines changed

crates/flycheck/src/lib.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,14 @@ impl FlycheckHandle {
100100
FlycheckHandle { id, sender, _thread: thread }
101101
}
102102

103-
/// Schedule a re-start of the cargo check worker.
104-
pub fn restart(&self) {
105-
self.sender.send(StateChange::Restart).unwrap();
103+
/// Schedule a re-start of the cargo check worker to do a workspace wide check.
104+
pub fn restart_workspace(&self) {
105+
self.sender.send(StateChange::Restart(None)).unwrap();
106+
}
107+
108+
/// Schedule a re-start of the cargo check worker to do a package wide check.
109+
pub fn restart_for_package(&self, package: String) {
110+
self.sender.send(StateChange::Restart(Some(package))).unwrap();
106111
}
107112

108113
/// Stop this cargo check worker.
@@ -153,7 +158,7 @@ pub enum Progress {
153158
}
154159

155160
enum StateChange {
156-
Restart,
161+
Restart(Option<String>),
157162
Cancel,
158163
}
159164

@@ -213,7 +218,7 @@ impl FlycheckActor {
213218
tracing::debug!(flycheck_id = self.id, "flycheck cancelled");
214219
self.cancel_check_process();
215220
}
216-
Event::RequestStateChange(StateChange::Restart) => {
221+
Event::RequestStateChange(StateChange::Restart(package)) => {
217222
// Cancel the previously spawned process
218223
self.cancel_check_process();
219224
while let Ok(restart) = inbox.recv_timeout(Duration::from_millis(50)) {
@@ -223,7 +228,7 @@ impl FlycheckActor {
223228
}
224229
}
225230

226-
let command = self.check_command();
231+
let command = self.check_command(package.as_deref());
227232
let formatted_command = format!("{:?}", command);
228233

229234
tracing::debug!(?command, "will restart flycheck");
@@ -297,7 +302,7 @@ impl FlycheckActor {
297302
}
298303
}
299304

300-
fn check_command(&self) -> Command {
305+
fn check_command(&self, package: Option<&str>) -> Command {
301306
let (mut cmd, args) = match &self.config {
302307
FlycheckConfig::CargoCommand {
303308
command,
@@ -314,7 +319,11 @@ impl FlycheckActor {
314319
let mut cmd = Command::new(toolchain::cargo());
315320
cmd.arg(command);
316321
cmd.current_dir(&self.root);
317-
cmd.arg("--workspace");
322+
323+
match package {
324+
Some(pkg) => cmd.arg("-p").arg(pkg),
325+
None => cmd.arg("--workspace"),
326+
};
318327

319328
cmd.arg(if *ansi_color_output {
320329
"--message-format=json-diagnostic-rendered-ansi"

crates/rust-analyzer/src/config.rs

+7
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ config_data! {
223223
///
224224
/// Aliased as `"checkOnSave.targets"`.
225225
check_targets | checkOnSave_targets | checkOnSave_target: Option<CheckOnSaveTargets> = "null",
226+
/// Whether `--workspace` should be passed to `cargo check`.
227+
/// If false, `-p <package>` will be passed instead.
228+
check_workspace: bool = "true",
226229

227230
/// Toggles the additional completions that automatically add imports when completed.
228231
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -1323,6 +1326,10 @@ impl Config {
13231326
}
13241327
}
13251328

1329+
pub fn flycheck_workspace(&self) -> bool {
1330+
self.data.check_workspace
1331+
}
1332+
13261333
pub fn flycheck(&self) -> FlycheckConfig {
13271334
match &self.data.check_overrideCommand {
13281335
Some(args) if !args.is_empty() => {

crates/rust-analyzer/src/handlers/notification.rs

+31-18
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub(crate) fn handle_did_save_text_document(
160160
} else if state.config.check_on_save() {
161161
// No specific flycheck was triggered, so let's trigger all of them.
162162
for flycheck in state.flycheck.iter() {
163-
flycheck.restart();
163+
flycheck.restart_workspace();
164164
}
165165
}
166166
Ok(())
@@ -281,35 +281,48 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
281281
let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
282282

283283
// Find all workspaces that have at least one target containing the saved file
284-
let workspace_ids = world.workspaces.iter().enumerate().filter(|(_, ws)| match ws {
285-
project_model::ProjectWorkspace::Cargo { cargo, .. } => {
286-
cargo.packages().any(|pkg| {
287-
cargo[pkg]
288-
.targets
289-
.iter()
290-
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()))
291-
})
292-
}
293-
project_model::ProjectWorkspace::Json { project, .. } => {
294-
project.crates().any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c))
295-
}
296-
project_model::ProjectWorkspace::DetachedFiles { .. } => false,
284+
let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
285+
let package = match ws {
286+
project_model::ProjectWorkspace::Cargo { cargo, .. } => {
287+
cargo.packages().find_map(|pkg| {
288+
let has_target_with_root = cargo[pkg]
289+
.targets
290+
.iter()
291+
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
292+
has_target_with_root.then(|| cargo[pkg].name.clone())
293+
})
294+
}
295+
project_model::ProjectWorkspace::Json { project, .. } => {
296+
if !project
297+
.crates()
298+
.any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c))
299+
{
300+
return None;
301+
}
302+
None
303+
}
304+
project_model::ProjectWorkspace::DetachedFiles { .. } => return None,
305+
};
306+
Some((idx, package))
297307
});
298308

299309
// Find and trigger corresponding flychecks
300310
for flycheck in world.flycheck.iter() {
301-
for (id, _) in workspace_ids.clone() {
311+
for (id, package) in workspace_ids.clone() {
302312
if id == flycheck.id() {
303313
updated = true;
304-
flycheck.restart();
314+
match package.filter(|_| !world.config.flycheck_workspace()) {
315+
Some(package) => flycheck.restart_for_package(package),
316+
None => flycheck.restart_workspace(),
317+
}
305318
continue;
306319
}
307320
}
308321
}
309322
// No specific flycheck was triggered, so let's trigger all of them.
310323
if !updated {
311324
for flycheck in world.flycheck.iter() {
312-
flycheck.restart();
325+
flycheck.restart_workspace();
313326
}
314327
}
315328
Ok(())
@@ -351,7 +364,7 @@ pub(crate) fn handle_run_flycheck(
351364
}
352365
// No specific flycheck was triggered, so let's trigger all of them.
353366
for flycheck in state.flycheck.iter() {
354-
flycheck.restart();
367+
flycheck.restart_workspace();
355368
}
356369
Ok(())
357370
}

crates/rust-analyzer/src/main_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl GlobalState {
314314
if became_quiescent {
315315
if self.config.check_on_save() {
316316
// Project has loaded properly, kick off initial flycheck
317-
self.flycheck.iter().for_each(FlycheckHandle::restart);
317+
self.flycheck.iter().for_each(FlycheckHandle::restart_workspace);
318318
}
319319
if self.config.prefill_caches() {
320320
self.prime_caches_queue.request_op("became quiescent".to_string(), ());

crates/rust-analyzer/src/reload.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ impl GlobalState {
503503
let mut crate_graph_file_dependencies = FxHashSet::default();
504504

505505
let mut load = |path: &AbsPath| {
506-
let _p = tracing::span!(tracing::Level::INFO, "switch_workspaces::load").entered();
506+
let _p = tracing::span!(tracing::Level::DEBUG, "switch_workspaces::load").entered();
507507
let vfs_path = vfs::VfsPath::from(path.to_path_buf());
508508
crate_graph_file_dependencies.insert(vfs_path.clone());
509509
match vfs.file_id(&vfs_path) {

docs/user/generated_config.adoc

+6
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets,
251251

252252
Aliased as `"checkOnSave.targets"`.
253253
--
254+
[[rust-analyzer.check.workspace]]rust-analyzer.check.workspace (default: `true`)::
255+
+
256+
--
257+
Whether `--workspace` should be passed to `cargo check`.
258+
If false, `-p <package>` will be passed instead.
259+
--
254260
[[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
255261
+
256262
--

editors/code/package.json

+5
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,11 @@
803803
}
804804
]
805805
},
806+
"rust-analyzer.check.workspace": {
807+
"markdownDescription": "Whether `--workspace` should be passed to `cargo check`.\nIf false, `-p <package>` will be passed instead.",
808+
"default": true,
809+
"type": "boolean"
810+
},
806811
"rust-analyzer.completion.autoimport.enable": {
807812
"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.",
808813
"default": true,

0 commit comments

Comments
 (0)