Skip to content

Commit 3cf17dc

Browse files
committed
Auto merge of #17472 - duncanawoods:master, r=HKalbasi
#17470 - run unit tests at the crate level not workspace For #17470 Use the test path to identify a package in the workspace and run the unit test there instead of at the workspace.
2 parents a467883 + 20d3237 commit 3cf17dc

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

crates/flycheck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub mod project_json;
2424
mod test_runner;
2525

2626
use command::{CommandHandle, ParseFromLine};
27-
pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState};
27+
pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState, TestTarget};
2828

2929
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
3030
pub enum InvocationStrategy {

crates/flycheck/src/test_runner.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,38 @@ pub struct CargoTestHandle {
5959
}
6060

6161
// Example of a cargo test command:
62-
// cargo test --workspace --no-fail-fast -- module::func -Z unstable-options --format=json
62+
// cargo test --workspace --no-fail-fast -- -Z unstable-options --format=json
63+
// or
64+
// cargo test --package my-package --no-fail-fast -- module::func -Z unstable-options --format=json
65+
66+
#[derive(Debug)]
67+
pub enum TestTarget {
68+
Workspace,
69+
Package(String),
70+
}
6371

6472
impl CargoTestHandle {
6573
pub fn new(
6674
path: Option<&str>,
6775
options: CargoOptions,
6876
root: &AbsPath,
77+
test_target: TestTarget,
6978
sender: Sender<CargoTestMessage>,
7079
) -> std::io::Result<Self> {
7180
let mut cmd = Command::new(Tool::Cargo.path());
7281
cmd.env("RUSTC_BOOTSTRAP", "1");
7382
cmd.arg("test");
74-
cmd.arg("--workspace");
83+
84+
match &test_target {
85+
TestTarget::Package(package) => {
86+
cmd.arg("--package");
87+
cmd.arg(package);
88+
}
89+
TestTarget::Workspace => {
90+
cmd.arg("--workspace");
91+
}
92+
};
93+
7594
// --no-fail-fast is needed to ensure that all requested tests will run
7695
cmd.arg("--no-fail-fast");
7796
cmd.arg("--manifest-path");

crates/rust-analyzer/src/handlers/request.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use lsp_types::{
2727
SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
2828
};
2929
use paths::Utf8PathBuf;
30-
use project_model::{ManifestPath, ProjectWorkspaceKind, TargetKind};
30+
use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind};
3131
use serde_json::json;
3232
use stdx::{format_to, never};
3333
use syntax::{algo, ast, AstNode, TextRange, TextSize};
@@ -199,14 +199,28 @@ pub(crate) fn handle_view_item_tree(
199199
Ok(res)
200200
}
201201

202+
// cargo test requires the real package name which might contain hyphens but
203+
// the test identifier passed to this function is the namespace form where hyphens
204+
// are replaced with underscores so we have to reverse this and find the real package name
205+
fn find_package_name(namespace_root: &str, cargo: &CargoWorkspace) -> Option<String> {
206+
cargo.packages().find_map(|p| {
207+
let package_name = &cargo[p].name;
208+
if package_name.replace('-', "_") == namespace_root {
209+
Some(package_name.clone())
210+
} else {
211+
None
212+
}
213+
})
214+
}
215+
202216
pub(crate) fn handle_run_test(
203217
state: &mut GlobalState,
204218
params: lsp_ext::RunTestParams,
205219
) -> anyhow::Result<()> {
206220
if let Some(_session) = state.test_run_session.take() {
207221
state.send_notification::<lsp_ext::EndRunTest>(());
208222
}
209-
// We detect the lowest common ansector of all included tests, and
223+
// We detect the lowest common ancestor of all included tests, and
210224
// run it. We ignore excluded tests for now, the client will handle
211225
// it for us.
212226
let lca = match params.include {
@@ -225,20 +239,31 @@ pub(crate) fn handle_run_test(
225239
.unwrap_or_default(),
226240
None => "".to_owned(),
227241
};
228-
let test_path = if lca.is_empty() {
229-
None
230-
} else if let Some((_, path)) = lca.split_once("::") {
231-
Some(path)
242+
let (namespace_root, test_path) = if lca.is_empty() {
243+
(None, None)
244+
} else if let Some((namespace_root, path)) = lca.split_once("::") {
245+
(Some(namespace_root), Some(path))
232246
} else {
233-
None
247+
(Some(lca.as_str()), None)
234248
};
235249
let mut handles = vec![];
236250
for ws in &*state.workspaces {
237251
if let ProjectWorkspaceKind::Cargo { cargo, .. } = &ws.kind {
252+
let test_target = if let Some(namespace_root) = namespace_root {
253+
if let Some(package_name) = find_package_name(namespace_root, cargo) {
254+
flycheck::TestTarget::Package(package_name)
255+
} else {
256+
flycheck::TestTarget::Workspace
257+
}
258+
} else {
259+
flycheck::TestTarget::Workspace
260+
};
261+
238262
let handle = flycheck::CargoTestHandle::new(
239263
test_path,
240264
state.config.cargo_test_options(),
241265
cargo.workspace_root(),
266+
test_target,
242267
state.test_run_sender.clone(),
243268
)?;
244269
handles.push(handle);

0 commit comments

Comments
 (0)