Skip to content

Commit c535487

Browse files
bors[bot]bcully
andauthored
Merge #10503
10503: Only include targets of packages that are workspace members r=Veykril a=bcully CargoWorkspace's package list includes packages that are path dependencies, even if those packages aren't actually members of the cargo workspace. As a result, rust-analyzer's runnable finder, which returns the target from the first workspace that has a matching package, may select the wrong working directory, causing runnables to fail, e.g., ``` error: package `root` cannot be tested because it requires dev-dependencies and is not a member of the workspace ``` To fix this, we filter out packages that aren't members of the workspace when searching for targets. Fixes #7764 Co-authored-by: Brendan Cully <[email protected]>
2 parents f87debc + 841d4f9 commit c535487

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

crates/project_model/src/cargo_workspace.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ pub struct PackageData {
137137
pub targets: Vec<Target>,
138138
/// Does this package come from the local filesystem (and is editable)?
139139
pub is_local: bool,
140+
// Whether this package is a member of the workspace
141+
pub is_member: bool,
140142
/// List of packages this package depends on
141143
pub dependencies: Vec<PackageDependency>,
142144
/// Rust edition for this package
@@ -296,6 +298,8 @@ impl CargoWorkspace {
296298
let mut packages = Arena::default();
297299
let mut targets = Arena::default();
298300

301+
let ws_members = &meta.workspace_members;
302+
299303
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
300304
for meta_pkg in &meta.packages {
301305
let cargo_metadata::Package {
@@ -309,6 +313,7 @@ impl CargoWorkspace {
309313
// We treat packages without source as "local" packages. That includes all members of
310314
// the current workspace, as well as any path dependency outside the workspace.
311315
let is_local = meta_pkg.source.is_none();
316+
let is_member = ws_members.contains(id);
312317

313318
let pkg = packages.alloc(PackageData {
314319
id: id.repr.clone(),
@@ -317,6 +322,7 @@ impl CargoWorkspace {
317322
manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)).try_into().unwrap(),
318323
targets: Vec::new(),
319324
is_local,
325+
is_member,
320326
edition,
321327
dependencies: Vec::new(),
322328
features: meta_pkg.features.clone().into_iter().collect(),
@@ -383,8 +389,8 @@ impl CargoWorkspace {
383389

384390
pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
385391
self.packages()
386-
.filter_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
387-
.next()
392+
.filter(|&pkg| self[pkg].is_member)
393+
.find_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
388394
.copied()
389395
}
390396

crates/rust-analyzer/tests/slow-tests/main.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,93 @@ fn main() {}
202202
);
203203
}
204204

205+
// Each package in these workspaces should be run from its own root
206+
#[test]
207+
fn test_path_dependency_runnables() {
208+
if skip_slow_tests() {
209+
return;
210+
}
211+
212+
let server = Project::with_fixture(
213+
r#"
214+
//- /consumer/Cargo.toml
215+
[package]
216+
name = "consumer"
217+
version = "0.1.0"
218+
[dependencies]
219+
dependency = { path = "../dependency" }
220+
221+
//- /consumer/src/lib.rs
222+
#[cfg(test)]
223+
mod tests {
224+
#[test]
225+
fn consumer() {}
226+
}
227+
228+
//- /dependency/Cargo.toml
229+
[package]
230+
name = "dependency"
231+
version = "0.1.0"
232+
[dev-dependencies]
233+
devdependency = { path = "../devdependency" }
234+
235+
//- /dependency/src/lib.rs
236+
#[cfg(test)]
237+
mod tests {
238+
#[test]
239+
fn dependency() {}
240+
}
241+
242+
//- /devdependency/Cargo.toml
243+
[package]
244+
name = "devdependency"
245+
version = "0.1.0"
246+
247+
//- /devdependency/src/lib.rs
248+
#[cfg(test)]
249+
mod tests {
250+
#[test]
251+
fn devdependency() {}
252+
}
253+
"#,
254+
)
255+
.root("consumer")
256+
.root("dependency")
257+
.root("devdependency")
258+
.server()
259+
.wait_until_workspace_is_loaded();
260+
261+
for runnable in ["consumer", "dependency", "devdependency"] {
262+
server.request::<Runnables>(
263+
RunnablesParams {
264+
text_document: server.doc_id(&format!("{}/src/lib.rs", runnable)),
265+
position: None,
266+
},
267+
json!([
268+
"{...}",
269+
{
270+
"label": "cargo test -p [..] --all-targets",
271+
"kind": "cargo",
272+
"args": {
273+
"overrideCargo": null,
274+
"workspaceRoot": server.path().join(runnable),
275+
"cargoArgs": [
276+
"test",
277+
"--package",
278+
runnable,
279+
"--all-targets"
280+
],
281+
"cargoExtraArgs": [],
282+
"executableArgs": []
283+
},
284+
},
285+
"{...}",
286+
"{...}"
287+
]),
288+
);
289+
}
290+
}
291+
205292
#[test]
206293
fn test_format_document() {
207294
if skip_slow_tests() {

0 commit comments

Comments
 (0)