mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #18845 from Veykril/push-yyuolqomnkys
fix: Fix flycheck getting confused which package to check
This commit is contained in:
commit
c89c03fd5a
@ -39,7 +39,7 @@ pub(crate) struct CargoOptions {
|
|||||||
pub(crate) target_dir: Option<Utf8PathBuf>,
|
pub(crate) target_dir: Option<Utf8PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum Target {
|
pub(crate) enum Target {
|
||||||
Bin(String),
|
Bin(String),
|
||||||
Example(String),
|
Example(String),
|
||||||
|
@ -726,7 +726,6 @@ impl GlobalStateSnapshot {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return Some(TargetSpec::ProjectJson(ProjectJsonTargetSpec {
|
return Some(TargetSpec::ProjectJson(ProjectJsonTargetSpec {
|
||||||
crate_id,
|
|
||||||
label: build.label,
|
label: build.label,
|
||||||
target_kind: build.target_kind,
|
target_kind: build.target_kind,
|
||||||
shell_runnables: project.runnables().to_owned(),
|
shell_runnables: project.runnables().to_owned(),
|
||||||
|
@ -10,7 +10,6 @@ use lsp_types::{
|
|||||||
DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
|
DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
|
||||||
};
|
};
|
||||||
use paths::Utf8PathBuf;
|
use paths::Utf8PathBuf;
|
||||||
use stdx::TupleExt;
|
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
use vfs::{AbsPathBuf, ChangeKind, VfsPath};
|
use vfs::{AbsPathBuf, ChangeKind, VfsPath};
|
||||||
|
|
||||||
@ -75,7 +74,6 @@ pub(crate) fn handle_did_open_text_document(
|
|||||||
tracing::error!("duplicate DidOpenTextDocument: {}", path);
|
tracing::error!("duplicate DidOpenTextDocument: {}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
tracing::info!("New file content set {:?}", params.text_document.text);
|
|
||||||
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
||||||
if state.config.discover_workspace_config().is_some() {
|
if state.config.discover_workspace_config().is_some() {
|
||||||
tracing::debug!("queuing task");
|
tracing::debug!("queuing task");
|
||||||
@ -296,12 +294,11 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
|
|||||||
let may_flycheck_workspace = state.config.flycheck_workspace(None);
|
let may_flycheck_workspace = state.config.flycheck_workspace(None);
|
||||||
let mut updated = false;
|
let mut updated = false;
|
||||||
let task = move || -> std::result::Result<(), ide::Cancelled> {
|
let task = move || -> std::result::Result<(), ide::Cancelled> {
|
||||||
// Is the target binary? If so we let flycheck run only for the workspace that contains the crate.
|
|
||||||
let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
|
let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
|
||||||
let tgt_kind = it.target_kind();
|
let tgt_kind = it.target_kind();
|
||||||
let (tgt_name, crate_id) = match it {
|
let (tgt_name, root, package) = match it {
|
||||||
TargetSpec::Cargo(c) => (c.target, c.crate_id),
|
TargetSpec::Cargo(c) => (c.target, c.workspace_root, c.package),
|
||||||
TargetSpec::ProjectJson(p) => (p.label, p.crate_id),
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let tgt = match tgt_kind {
|
let tgt = match tgt_kind {
|
||||||
@ -309,28 +306,50 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
|
|||||||
project_model::TargetKind::Example => Target::Example(tgt_name),
|
project_model::TargetKind::Example => Target::Example(tgt_name),
|
||||||
project_model::TargetKind::Test => Target::Test(tgt_name),
|
project_model::TargetKind::Test => Target::Test(tgt_name),
|
||||||
project_model::TargetKind::Bench => Target::Benchmark(tgt_name),
|
project_model::TargetKind::Bench => Target::Benchmark(tgt_name),
|
||||||
_ => return None,
|
_ => return Some((None, root, package)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((tgt, crate_id))
|
Some((Some(tgt), root, package))
|
||||||
});
|
});
|
||||||
|
tracing::debug!(?target, "flycheck target");
|
||||||
let crate_ids = match target {
|
// we have a specific non-library target, attempt to only check that target, nothing
|
||||||
// Trigger flychecks for the only crate which the target belongs to
|
// else will be affected
|
||||||
Some((_, krate)) => vec![krate],
|
if let Some((target, root, package)) = target {
|
||||||
None => {
|
// trigger a package check if we have a non-library target as that can't affect
|
||||||
// Trigger flychecks for all workspaces that depend on the saved file
|
// anything else in the workspace OR if we're not allowed to check the workspace as
|
||||||
// Crates containing or depending on the saved file
|
// the user opted into package checks then
|
||||||
world
|
let package_check_allowed = target.is_some() || !may_flycheck_workspace;
|
||||||
.analysis
|
if package_check_allowed {
|
||||||
.crates_for(file_id)?
|
let workspace =
|
||||||
.into_iter()
|
world.workspaces.iter().enumerate().find(|(_, ws)| match &ws.kind {
|
||||||
.flat_map(|id| world.analysis.transitive_rev_deps(id))
|
project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
|
||||||
.flatten()
|
| project_model::ProjectWorkspaceKind::DetachedFile {
|
||||||
.unique()
|
cargo: Some((cargo, _, _)),
|
||||||
.collect::<Vec<_>>()
|
..
|
||||||
|
} => *cargo.workspace_root() == root,
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
if let Some((idx, _)) = workspace {
|
||||||
|
world.flycheck[idx].restart_for_package(package, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if !may_flycheck_workspace {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger flychecks for all workspaces that depend on the saved file
|
||||||
|
// Crates containing or depending on the saved file
|
||||||
|
let crate_ids = world
|
||||||
|
.analysis
|
||||||
|
.crates_for(file_id)?
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|id| world.analysis.transitive_rev_deps(id))
|
||||||
|
.flatten()
|
||||||
|
.unique()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
tracing::debug!(?crate_ids, "flycheck crate ids");
|
||||||
let crate_root_paths: Vec<_> = crate_ids
|
let crate_root_paths: Vec<_> = crate_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|&crate_id| {
|
.filter_map(|&crate_id| {
|
||||||
@ -344,53 +363,41 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
|
|||||||
})
|
})
|
||||||
.collect::<ide::Cancellable<_>>()?;
|
.collect::<ide::Cancellable<_>>()?;
|
||||||
let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
|
let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
|
||||||
|
tracing::debug!(?crate_root_paths, "flycheck crate roots");
|
||||||
|
|
||||||
// Find all workspaces that have at least one target containing the saved file
|
// Find all workspaces that have at least one target containing the saved file
|
||||||
let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
|
let workspace_ids =
|
||||||
let package = match &ws.kind {
|
world.workspaces.iter().enumerate().filter(|(_, ws)| match &ws.kind {
|
||||||
project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
|
project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
|
||||||
| project_model::ProjectWorkspaceKind::DetachedFile {
|
| project_model::ProjectWorkspaceKind::DetachedFile {
|
||||||
cargo: Some((cargo, _, _)),
|
cargo: Some((cargo, _, _)),
|
||||||
..
|
..
|
||||||
} => cargo.packages().find_map(|pkg| {
|
} => cargo.packages().any(|pkg| {
|
||||||
let has_target_with_root = cargo[pkg]
|
cargo[pkg]
|
||||||
.targets
|
.targets
|
||||||
.iter()
|
.iter()
|
||||||
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
|
.any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()))
|
||||||
has_target_with_root.then(|| cargo.package_flag(&cargo[pkg]))
|
|
||||||
}),
|
}),
|
||||||
project_model::ProjectWorkspaceKind::Json(project) => {
|
project_model::ProjectWorkspaceKind::Json(project) => project
|
||||||
if !project.crates().any(|(_, krate)| {
|
.crates()
|
||||||
crate_root_paths.contains(&krate.root_module.as_path())
|
.any(|(_, krate)| crate_root_paths.contains(&krate.root_module.as_path())),
|
||||||
}) {
|
project_model::ProjectWorkspaceKind::DetachedFile { .. } => false,
|
||||||
return None;
|
});
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
project_model::ProjectWorkspaceKind::DetachedFile { .. } => return None,
|
|
||||||
};
|
|
||||||
Some((idx, package))
|
|
||||||
});
|
|
||||||
|
|
||||||
let saved_file = vfs_path.as_path().map(|p| p.to_owned());
|
let saved_file = vfs_path.as_path().map(|p| p.to_owned());
|
||||||
|
|
||||||
// Find and trigger corresponding flychecks
|
// Find and trigger corresponding flychecks
|
||||||
'flychecks: for flycheck in world.flycheck.iter() {
|
'flychecks: for flycheck in world.flycheck.iter() {
|
||||||
for (id, package) in workspace_ids.clone() {
|
for (id, _) in workspace_ids.clone() {
|
||||||
if id == flycheck.id() {
|
if id == flycheck.id() {
|
||||||
updated = true;
|
updated = true;
|
||||||
if may_flycheck_workspace {
|
flycheck.restart_workspace(saved_file.clone());
|
||||||
flycheck.restart_workspace(saved_file.clone())
|
|
||||||
} else if let Some(package) = package {
|
|
||||||
flycheck
|
|
||||||
.restart_for_package(package, target.clone().map(TupleExt::head))
|
|
||||||
}
|
|
||||||
continue 'flychecks;
|
continue 'flychecks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No specific flycheck was triggered, so let's trigger all of them.
|
// No specific flycheck was triggered, so let's trigger all of them.
|
||||||
if !updated && may_flycheck_workspace {
|
if !updated {
|
||||||
for flycheck in world.flycheck.iter() {
|
for flycheck in world.flycheck.iter() {
|
||||||
flycheck.restart_workspace(saved_file.clone());
|
flycheck.restart_workspace(saved_file.clone());
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ pub(crate) struct CargoTargetSpec {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct ProjectJsonTargetSpec {
|
pub(crate) struct ProjectJsonTargetSpec {
|
||||||
pub(crate) crate_id: CrateId,
|
|
||||||
pub(crate) label: String,
|
pub(crate) label: String,
|
||||||
pub(crate) target_kind: TargetKind,
|
pub(crate) target_kind: TargetKind,
|
||||||
pub(crate) shell_runnables: Vec<Runnable>,
|
pub(crate) shell_runnables: Vec<Runnable>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user