Skip to content

Commit 68c2241

Browse files
authored
Merge pull request #18845 from Veykril/push-yyuolqomnkys
fix: Fix flycheck getting confused which package to check
2 parents aeae353 + e47bb0d commit 68c2241

File tree

4 files changed

+58
-53
lines changed

4 files changed

+58
-53
lines changed

src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(crate) struct CargoOptions {
3939
pub(crate) target_dir: Option<Utf8PathBuf>,
4040
}
4141

42-
#[derive(Clone)]
42+
#[derive(Clone, Debug)]
4343
pub(crate) enum Target {
4444
Bin(String),
4545
Example(String),

src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,6 @@ impl GlobalStateSnapshot {
726726
};
727727

728728
return Some(TargetSpec::ProjectJson(ProjectJsonTargetSpec {
729-
crate_id,
730729
label: build.label,
731730
target_kind: build.target_kind,
732731
shell_runnables: project.runnables().to_owned(),

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

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use lsp_types::{
1010
DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
1111
};
1212
use paths::Utf8PathBuf;
13-
use stdx::TupleExt;
1413
use triomphe::Arc;
1514
use vfs::{AbsPathBuf, ChangeKind, VfsPath};
1615

@@ -75,7 +74,6 @@ pub(crate) fn handle_did_open_text_document(
7574
tracing::error!("duplicate DidOpenTextDocument: {}", path);
7675
}
7776

78-
tracing::info!("New file content set {:?}", params.text_document.text);
7977
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
8078
if state.config.discover_workspace_config().is_some() {
8179
tracing::debug!("queuing task");
@@ -296,41 +294,62 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
296294
let may_flycheck_workspace = state.config.flycheck_workspace(None);
297295
let mut updated = false;
298296
let task = move || -> std::result::Result<(), ide::Cancelled> {
299-
// Is the target binary? If so we let flycheck run only for the workspace that contains the crate.
300297
let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
301298
let tgt_kind = it.target_kind();
302-
let (tgt_name, crate_id) = match it {
303-
TargetSpec::Cargo(c) => (c.target, c.crate_id),
304-
TargetSpec::ProjectJson(p) => (p.label, p.crate_id),
299+
let (tgt_name, root, package) = match it {
300+
TargetSpec::Cargo(c) => (c.target, c.workspace_root, c.package),
301+
_ => return None,
305302
};
306303

307304
let tgt = match tgt_kind {
308305
project_model::TargetKind::Bin => Target::Bin(tgt_name),
309306
project_model::TargetKind::Example => Target::Example(tgt_name),
310307
project_model::TargetKind::Test => Target::Test(tgt_name),
311308
project_model::TargetKind::Bench => Target::Benchmark(tgt_name),
312-
_ => return None,
309+
_ => return Some((None, root, package)),
313310
};
314311

315-
Some((tgt, crate_id))
312+
Some((Some(tgt), root, package))
316313
});
317-
318-
let crate_ids = match target {
319-
// Trigger flychecks for the only crate which the target belongs to
320-
Some((_, krate)) => vec![krate],
321-
None => {
322-
// Trigger flychecks for all workspaces that depend on the saved file
323-
// Crates containing or depending on the saved file
324-
world
325-
.analysis
326-
.crates_for(file_id)?
327-
.into_iter()
328-
.flat_map(|id| world.analysis.transitive_rev_deps(id))
329-
.flatten()
330-
.unique()
331-
.collect::<Vec<_>>()
314+
tracing::debug!(?target, "flycheck target");
315+
// we have a specific non-library target, attempt to only check that target, nothing
316+
// else will be affected
317+
if let Some((target, root, package)) = target {
318+
// trigger a package check if we have a non-library target as that can't affect
319+
// anything else in the workspace OR if we're not allowed to check the workspace as
320+
// the user opted into package checks then
321+
let package_check_allowed = target.is_some() || !may_flycheck_workspace;
322+
if package_check_allowed {
323+
let workspace =
324+
world.workspaces.iter().enumerate().find(|(_, ws)| match &ws.kind {
325+
project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
326+
| project_model::ProjectWorkspaceKind::DetachedFile {
327+
cargo: Some((cargo, _, _)),
328+
..
329+
} => *cargo.workspace_root() == root,
330+
_ => false,
331+
});
332+
if let Some((idx, _)) = workspace {
333+
world.flycheck[idx].restart_for_package(package, target);
334+
}
332335
}
333-
};
336+
}
337+
338+
if !may_flycheck_workspace {
339+
return Ok(());
340+
}
341+
342+
// Trigger flychecks for all workspaces that depend on the saved file
343+
// Crates containing or depending on the saved file
344+
let crate_ids = world
345+
.analysis
346+
.crates_for(file_id)?
347+
.into_iter()
348+
.flat_map(|id| world.analysis.transitive_rev_deps(id))
349+
.flatten()
350+
.unique()
351+
.collect::<Vec<_>>();
352+
tracing::debug!(?crate_ids, "flycheck crate ids");
334353
let crate_root_paths: Vec<_> = crate_ids
335354
.iter()
336355
.filter_map(|&crate_id| {
@@ -344,53 +363,41 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
344363
})
345364
.collect::<ide::Cancellable<_>>()?;
346365
let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
366+
tracing::debug!(?crate_root_paths, "flycheck crate roots");
347367

348368
// Find all workspaces that have at least one target containing the saved file
349-
let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
350-
let package = match &ws.kind {
369+
let workspace_ids =
370+
world.workspaces.iter().enumerate().filter(|(_, ws)| match &ws.kind {
351371
project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
352372
| project_model::ProjectWorkspaceKind::DetachedFile {
353373
cargo: Some((cargo, _, _)),
354374
..
355-
} => cargo.packages().find_map(|pkg| {
356-
let has_target_with_root = cargo[pkg]
375+
} => cargo.packages().any(|pkg| {
376+
cargo[pkg]
357377
.targets
358378
.iter()
359-
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
360-
has_target_with_root.then(|| cargo.package_flag(&cargo[pkg]))
379+
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()))
361380
}),
362-
project_model::ProjectWorkspaceKind::Json(project) => {
363-
if !project.crates().any(|(_, krate)| {
364-
crate_root_paths.contains(&krate.root_module.as_path())
365-
}) {
366-
return None;
367-
}
368-
None
369-
}
370-
project_model::ProjectWorkspaceKind::DetachedFile { .. } => return None,
371-
};
372-
Some((idx, package))
373-
});
381+
project_model::ProjectWorkspaceKind::Json(project) => project
382+
.crates()
383+
.any(|(_, krate)| crate_root_paths.contains(&krate.root_module.as_path())),
384+
project_model::ProjectWorkspaceKind::DetachedFile { .. } => false,
385+
});
374386

375387
let saved_file = vfs_path.as_path().map(|p| p.to_owned());
376388

377389
// Find and trigger corresponding flychecks
378390
'flychecks: for flycheck in world.flycheck.iter() {
379-
for (id, package) in workspace_ids.clone() {
391+
for (id, _) in workspace_ids.clone() {
380392
if id == flycheck.id() {
381393
updated = true;
382-
if may_flycheck_workspace {
383-
flycheck.restart_workspace(saved_file.clone())
384-
} else if let Some(package) = package {
385-
flycheck
386-
.restart_for_package(package, target.clone().map(TupleExt::head))
387-
}
394+
flycheck.restart_workspace(saved_file.clone());
388395
continue 'flychecks;
389396
}
390397
}
391398
}
392399
// No specific flycheck was triggered, so let's trigger all of them.
393-
if !updated && may_flycheck_workspace {
400+
if !updated {
394401
for flycheck in world.flycheck.iter() {
395402
flycheck.restart_workspace(saved_file.clone());
396403
}

src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ pub(crate) struct CargoTargetSpec {
6262

6363
#[derive(Clone, Debug)]
6464
pub(crate) struct ProjectJsonTargetSpec {
65-
pub(crate) crate_id: CrateId,
6665
pub(crate) label: String,
6766
pub(crate) target_kind: TargetKind,
6867
pub(crate) shell_runnables: Vec<Runnable>,

0 commit comments

Comments
 (0)