Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/rust-analyzer/src/test_runner.rs')
| -rw-r--r-- | crates/rust-analyzer/src/test_runner.rs | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs index 3edfb812cf..9c0bc33af6 100644 --- a/crates/rust-analyzer/src/test_runner.rs +++ b/crates/rust-analyzer/src/test_runner.rs @@ -3,12 +3,13 @@ use crossbeam_channel::Sender; use paths::AbsPath; +use project_model::TargetKind; use serde::Deserialize as _; use serde_derive::Deserialize; use toolchain::Tool; use crate::{ - command::{CommandHandle, ParseFromLine}, + command::{CargoParser, CommandHandle}, flycheck::CargoOptions, }; @@ -25,9 +26,15 @@ pub(crate) enum TestState { }, } +#[derive(Debug)] +pub(crate) struct CargoTestMessage { + pub target: TestTarget, + pub output: CargoTestOutput, +} + #[derive(Debug, Deserialize)] #[serde(tag = "type", rename_all = "camelCase")] -pub(crate) enum CargoTestMessage { +pub(crate) enum CargoTestOutput { Test { name: String, #[serde(flatten)] @@ -40,19 +47,33 @@ pub(crate) enum CargoTestMessage { }, } -impl ParseFromLine for CargoTestMessage { - fn from_line(line: &str, _: &mut String) -> Option<Self> { +pub(crate) struct CargoTestOutputParser { + pub target: TestTarget, +} + +impl CargoTestOutputParser { + pub(crate) fn new(test_target: &TestTarget) -> Self { + Self { target: test_target.clone() } + } +} + +impl CargoParser<CargoTestMessage> for CargoTestOutputParser { + fn from_line(&self, line: &str, _error: &mut String) -> Option<CargoTestMessage> { let mut deserializer = serde_json::Deserializer::from_str(line); deserializer.disable_recursion_limit(); - if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) { - return Some(message); - } - Some(CargoTestMessage::Custom { text: line.to_owned() }) + Some(CargoTestMessage { + target: self.target.clone(), + output: if let Ok(message) = CargoTestOutput::deserialize(&mut deserializer) { + message + } else { + CargoTestOutput::Custom { text: line.to_owned() } + }, + }) } - fn from_eof() -> Option<Self> { - Some(CargoTestMessage::Finished) + fn from_eof(&self) -> Option<CargoTestMessage> { + Some(CargoTestMessage { target: self.target.clone(), output: CargoTestOutput::Finished }) } } @@ -62,14 +83,14 @@ pub(crate) struct CargoTestHandle { } // Example of a cargo test command: -// cargo test --workspace --no-fail-fast -- -Z unstable-options --format=json -// or -// cargo test --package my-package --no-fail-fast -- module::func -Z unstable-options --format=json +// +// cargo test --package my-package --bin my_bin --no-fail-fast -- module::func -Z unstable-options --format=json -#[derive(Debug)] -pub(crate) enum TestTarget { - Workspace, - Package(String), +#[derive(Debug, Clone)] +pub(crate) struct TestTarget { + pub package: String, + pub target: String, + pub kind: TargetKind, } impl CargoTestHandle { @@ -80,19 +101,22 @@ impl CargoTestHandle { test_target: TestTarget, sender: Sender<CargoTestMessage>, ) -> std::io::Result<Self> { - let mut cmd = toolchain::command(Tool::Cargo.path(), root); + let mut cmd = toolchain::command(Tool::Cargo.path(), root, &options.extra_env); cmd.env("RUSTC_BOOTSTRAP", "1"); cmd.arg("test"); - match &test_target { - TestTarget::Package(package) => { - cmd.arg("--package"); - cmd.arg(package); - } - TestTarget::Workspace => { - cmd.arg("--workspace"); - } - }; + cmd.arg("--package"); + cmd.arg(&test_target.package); + + if let TargetKind::Lib { .. } = test_target.kind { + // no name required with lib because there can only be one lib target per package + cmd.arg("--lib"); + } else if let Some(cargo_target) = test_target.kind.as_cargo_target() { + cmd.arg(format!("--{cargo_target}")); + cmd.arg(&test_target.target); + } else { + tracing::warn!("Running test for unknown cargo target {:?}", test_target.kind); + } // --no-fail-fast is needed to ensure that all requested tests will run cmd.arg("--no-fail-fast"); @@ -110,6 +134,8 @@ impl CargoTestHandle { cmd.arg(extra_arg); } - Ok(Self { _handle: CommandHandle::spawn(cmd, sender)? }) + Ok(Self { + _handle: CommandHandle::spawn(cmd, CargoTestOutputParser::new(&test_target), sender)?, + }) } } |