Skip to content

Commit

Permalink
Auto merge of #16510 - Veykril:single-package-check, r=Veykril
Browse files Browse the repository at this point in the history
feat: Allow cargo check to run on only the current package

cc #13336, #12882
  • Loading branch information
bors committed Feb 8, 2024
2 parents bcc8a09 + 0258f60 commit ae89522
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 28 deletions.
25 changes: 17 additions & 8 deletions crates/flycheck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -153,7 +158,7 @@ pub enum Progress {
}

enum StateChange {
Restart,
Restart(Option<String>),
Cancel,
}

Expand Down Expand Up @@ -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)) {
Expand All @@ -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");
Expand Down Expand Up @@ -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,
Expand All @@ -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"
Expand Down
7 changes: 7 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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() => {
Expand Down
49 changes: 31 additions & 18 deletions crates/rust-analyzer/src/handlers/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down Expand Up @@ -281,35 +281,48 @@ 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;
}
}
}
// 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(())
Expand Down Expand Up @@ -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(())
}
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(), ());
Expand Down
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/reload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 6 additions & 0 deletions docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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`)::
+
--
Expand Down
5 changes: 5 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit ae89522

Please sign in to comment.