Skip to content

Commit 9abf32d

Browse files
committed
fix: Make flycheck clearing dependency-aware
1 parent 85b6332 commit 9abf32d

File tree

8 files changed

+213
-43
lines changed

8 files changed

+213
-43
lines changed

crates/project-model/src/build_dependencies.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use std::{cell::RefCell, io, mem, process::Command};
1010

1111
use base_db::Env;
12-
use cargo_metadata::{Message, camino::Utf8Path};
12+
use cargo_metadata::{Message, PackageId, camino::Utf8Path};
1313
use cfg::CfgAtom;
1414
use itertools::Itertools;
1515
use la_arena::ArenaMap;
@@ -18,6 +18,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
1818
use serde::Deserialize as _;
1919
use stdx::never;
2020
use toolchain::Tool;
21+
use triomphe::Arc;
2122

2223
use crate::{
2324
CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, Package, Sysroot,
@@ -284,7 +285,7 @@ impl WorkspaceBuildScripts {
284285
// NB: Cargo.toml could have been modified between `cargo metadata` and
285286
// `cargo check`. We shouldn't assume that package ids we see here are
286287
// exactly those from `config`.
287-
let mut by_id: FxHashMap<String, Package> = FxHashMap::default();
288+
let mut by_id: FxHashMap<Arc<PackageId>, Package> = FxHashMap::default();
288289
for package in workspace.packages() {
289290
outputs.insert(package, BuildScriptOutput::default());
290291
by_id.insert(workspace[package].id.clone(), package);
@@ -323,7 +324,7 @@ impl WorkspaceBuildScripts {
323324
// ideally this would be something like:
324325
// with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)),
325326
// but owned trait objects aren't a thing
326-
mut with_output_for: impl FnMut(&str, &mut dyn FnMut(&str, &mut BuildScriptOutput)),
327+
mut with_output_for: impl FnMut(&PackageId, &mut dyn FnMut(&str, &mut BuildScriptOutput)),
327328
progress: &dyn Fn(String),
328329
) -> io::Result<Option<String>> {
329330
let errors = RefCell::new(String::new());
@@ -346,7 +347,7 @@ impl WorkspaceBuildScripts {
346347

347348
match message {
348349
Message::BuildScriptExecuted(mut message) => {
349-
with_output_for(&message.package_id.repr, &mut |name, data| {
350+
with_output_for(&message.package_id, &mut |name, data| {
350351
progress(format!("build script {name} run"));
351352
let cfgs = {
352353
let mut acc = Vec::new();
@@ -377,7 +378,7 @@ impl WorkspaceBuildScripts {
377378
});
378379
}
379380
Message::CompilerArtifact(message) => {
380-
with_output_for(&message.package_id.repr, &mut |name, data| {
381+
with_output_for(&message.package_id, &mut |name, data| {
381382
progress(format!("proc-macro {name} built"));
382383
if data.proc_macro_dylib_path == ProcMacroDylibPath::NotBuilt {
383384
data.proc_macro_dylib_path = ProcMacroDylibPath::NotProcMacro;

crates/project-model/src/cargo_workspace.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::str::from_utf8;
55

66
use anyhow::Context;
77
use base_db::Env;
8-
use cargo_metadata::{CargoOpt, MetadataCommand};
8+
use cargo_metadata::{CargoOpt, MetadataCommand, PackageId};
99
use la_arena::{Arena, Idx};
1010
use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
1111
use rustc_hash::{FxHashMap, FxHashSet};
@@ -14,6 +14,7 @@ use serde_json::from_value;
1414
use span::Edition;
1515
use stdx::process::spawn_with_streaming_output;
1616
use toolchain::Tool;
17+
use triomphe::Arc;
1718

1819
use crate::cargo_config_file::make_lockfile_copy;
1920
use crate::{CfgOverrides, InvocationStrategy};
@@ -155,8 +156,8 @@ pub struct PackageData {
155156
pub features: FxHashMap<String, Vec<String>>,
156157
/// List of features enabled on this package
157158
pub active_features: Vec<String>,
158-
/// String representation of package id
159-
pub id: String,
159+
/// Package id
160+
pub id: Arc<PackageId>,
160161
/// Authors as given in the `Cargo.toml`
161162
pub authors: Vec<String>,
162163
/// Description as given in the `Cargo.toml`
@@ -173,6 +174,10 @@ pub struct PackageData {
173174
pub rust_version: Option<semver::Version>,
174175
/// The contents of [package.metadata.rust-analyzer]
175176
pub metadata: RustAnalyzerPackageMetaData,
177+
/// If this is package is a member of the workspace, store all direct and transitive
178+
/// dependencies as long as they are workspace members, to track dependency relationships
179+
/// between members.
180+
pub all_member_deps: Option<FxHashSet<Package>>,
176181
}
177182

178183
#[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)]
@@ -334,6 +339,8 @@ impl CargoWorkspace {
334339
let mut is_virtual_workspace = true;
335340
let mut requires_rustc_private = false;
336341

342+
let mut members = FxHashSet::default();
343+
337344
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
338345
for meta_pkg in meta.packages {
339346
let cargo_metadata::Package {
@@ -356,6 +363,7 @@ impl CargoWorkspace {
356363
rust_version,
357364
..
358365
} = meta_pkg;
366+
let id = Arc::new(id);
359367
let meta = from_value::<PackageMetadata>(metadata).unwrap_or_default();
360368
let edition = match edition {
361369
cargo_metadata::Edition::E2015 => Edition::Edition2015,
@@ -375,7 +383,7 @@ impl CargoWorkspace {
375383
let manifest = ManifestPath::try_from(AbsPathBuf::assert(manifest_path)).unwrap();
376384
is_virtual_workspace &= manifest != ws_manifest_path;
377385
let pkg = packages.alloc(PackageData {
378-
id: id.repr.clone(),
386+
id: id.clone(),
379387
name: name.to_string(),
380388
version,
381389
manifest: manifest.clone(),
@@ -395,7 +403,11 @@ impl CargoWorkspace {
395403
features: features.into_iter().collect(),
396404
active_features: Vec::new(),
397405
metadata: meta.rust_analyzer.unwrap_or_default(),
406+
all_member_deps: None,
398407
});
408+
if is_member {
409+
members.insert(pkg);
410+
}
399411
let pkg_data = &mut packages[pkg];
400412
requires_rustc_private |= pkg_data.metadata.rustc_private;
401413
pkg_by_id.insert(id, pkg);
@@ -440,6 +452,43 @@ impl CargoWorkspace {
440452
.extend(node.features.into_iter().map(|it| it.to_string()));
441453
}
442454

455+
fn saturate_all_member_deps(
456+
packages: &mut Arena<PackageData>,
457+
to_visit: Package,
458+
visited: &mut FxHashSet<Package>,
459+
members: &FxHashSet<Package>,
460+
) {
461+
let pkg_data = &mut packages[to_visit];
462+
463+
if !visited.insert(to_visit) {
464+
return;
465+
}
466+
467+
let deps: Vec<_> = pkg_data
468+
.dependencies
469+
.iter()
470+
.filter_map(|dep| {
471+
let pkg = dep.pkg;
472+
if members.contains(&pkg) { Some(pkg) } else { None }
473+
})
474+
.collect();
475+
476+
let mut all_member_deps = FxHashSet::from_iter(deps.iter().copied());
477+
for dep in deps {
478+
saturate_all_member_deps(packages, dep, visited, members);
479+
if let Some(transitives) = &packages[dep].all_member_deps {
480+
all_member_deps.extend(transitives);
481+
}
482+
}
483+
484+
packages[to_visit].all_member_deps = Some(all_member_deps);
485+
}
486+
487+
let mut visited = FxHashSet::default();
488+
for member in members.iter() {
489+
saturate_all_member_deps(&mut packages, *member, &mut visited, &members);
490+
}
491+
443492
CargoWorkspace {
444493
packages,
445494
targets,

crates/rust-analyzer/src/diagnostics.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,29 @@ impl DiagnosticCollection {
120120
}
121121
}
122122

123+
pub(crate) fn clear_check_older_than_for_package(
124+
&mut self,
125+
flycheck_id: usize,
126+
package_id: Arc<PackageId>,
127+
generation: DiagnosticsGeneration,
128+
) {
129+
let Some(check) = self.check.get_mut(flycheck_id) else {
130+
return;
131+
};
132+
let package_id = Some(package_id);
133+
let Some((_, checks)) = check
134+
.per_package
135+
.extract_if(|k, v| *k == package_id && v.generation < generation)
136+
.next()
137+
else {
138+
return;
139+
};
140+
self.changes.extend(checks.per_file.into_keys());
141+
if let Some(fixes) = Arc::make_mut(&mut self.check_fixes).get_mut(flycheck_id) {
142+
fixes.remove(&package_id);
143+
}
144+
}
145+
123146
pub(crate) fn clear_native_for(&mut self, file_id: FileId) {
124147
self.native_syntax.remove(&file_id);
125148
self.native_semantic.remove(&file_id);

0 commit comments

Comments
 (0)