Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions crates/project-model/src/project_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,27 @@ pub enum RunnableKind {
/// May include {test_id} which will get the test clicked on by the user.
TestOne,

/// Run tests matching a pattern (in RA, usually a path::to::module::of::tests)
/// May include {label} which will get the label from the `build` section of a crate.
/// May include {test_pattern} which will get the test module clicked on by the user.
TestMod,

/// Run a single doctest
/// May include {label} which will get the label from the `build` section of a crate.
/// May include {test_id} which will get the doctest clicked on by the user.
DocTestOne,

/// Run a single benchmark
/// May include {label} which will get the label from the `build` section of a crate.
/// May include {bench_id} which will get the benchmark clicked on by the user.
BenchOne,

/// Template for checking a target, emitting rustc JSON diagnostics.
/// May include {label} which will get the label from the `build` section of a crate.
Flycheck,

/// For forwards-compatibility, i.e. old rust-analyzer binary with newer workspace discovery tools
Unknown,
}

#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -478,6 +496,14 @@ pub enum RunnableKindData {
Check,
Run,
TestOne,
TestMod,
DocTestOne,
BenchOne,

/// For forwards-compatibility, i.e. old rust-analyzer binary with newer workspace discovery tools
#[allow(unused)]
#[serde(other)]
Unknown,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
Expand Down Expand Up @@ -545,7 +571,11 @@ impl From<RunnableKindData> for RunnableKind {
RunnableKindData::Check => RunnableKind::Check,
RunnableKindData::Run => RunnableKind::Run,
RunnableKindData::TestOne => RunnableKind::TestOne,
RunnableKindData::TestMod => RunnableKind::TestMod,
RunnableKindData::DocTestOne => RunnableKind::DocTestOne,
RunnableKindData::BenchOne => RunnableKind::BenchOne,
RunnableKindData::Flycheck => RunnableKind::Flycheck,
RunnableKindData::Unknown => RunnableKind::Unknown,
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/project-model/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ fn rust_project_hello_world_project_model() {
);
}

#[test]
fn rust_project_labeled_project_model() {
// This just needs to parse.
_ = load_rust_project("labeled-project.json");
}

#[test]
fn rust_project_cfg_groups() {
let (crate_graph, _proc_macros) = load_rust_project("cfg-groups.json");
Expand Down
37 changes: 37 additions & 0 deletions crates/project-model/test_data/labeled-project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"sysroot_src": null,
"crates": [
{
"display_name": "hello_world",
"root_module": "$ROOT$src/lib.rs",
"edition": "2018",
"deps": [],
"is_workspace_member": true,
"build": {
"label": "//:hello_world",
"build_file": "$ROOT$BUILD",
"target_kind": "bin"
}
}
],
"runnables": [
{
"kind": "run",
"program": "bazel",
"args": ["run", "{label}"],
"cwd": "$ROOT$"
},
{
"kind": "flycheck",
"program": "$ROOT$custom-flychecker.sh",
"args": ["{label}"],
"cwd": "$ROOT$"
},
{
"kind": "we-ignore-unknown-runnable-kinds-for-forwards-compatibility",
"program": "abc",
"args": ["{label}"],
"cwd": "$ROOT$"
}
]
}
81 changes: 42 additions & 39 deletions crates/rust-analyzer/src/target_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cargo_metadata::PackageId;
use cfg::{CfgAtom, CfgExpr};
use hir::sym;
use ide::{Cancellable, Crate, FileId, RunnableKind, TestId};
use project_model::project_json::Runnable;
use project_model::project_json::{self, Runnable};
use project_model::{CargoFeatures, ManifestPath, TargetKind};
use rustc_hash::FxHashSet;
use triomphe::Arc;
Expand Down Expand Up @@ -72,48 +72,51 @@ pub(crate) struct ProjectJsonTargetSpec {
}

impl ProjectJsonTargetSpec {
fn find_replace_runnable(
&self,
kind: project_json::RunnableKind,
replacer: &dyn Fn(&Self, &str) -> String,
) -> Option<Runnable> {
for runnable in &self.shell_runnables {
if runnable.kind == kind {
let mut runnable = runnable.clone();

let replaced_args: Vec<_> =
runnable.args.iter().map(|arg| replacer(self, arg)).collect();
runnable.args = replaced_args;

return Some(runnable);
}
}

None
}

pub(crate) fn runnable_args(&self, kind: &RunnableKind) -> Option<Runnable> {
match kind {
RunnableKind::Bin => {
for runnable in &self.shell_runnables {
if matches!(runnable.kind, project_model::project_json::RunnableKind::Run) {
let mut runnable = runnable.clone();

let replaced_args: Vec<_> = runnable
.args
.iter()
.map(|arg| arg.replace("{label}", &self.label))
.collect();
runnable.args = replaced_args;

return Some(runnable);
}
}

None
}
RunnableKind::Bin => self
.find_replace_runnable(project_json::RunnableKind::Run, &|this, arg| {
arg.replace("{label}", &this.label)
}),
RunnableKind::Test { test_id, .. } => {
for runnable in &self.shell_runnables {
if matches!(runnable.kind, project_model::project_json::RunnableKind::TestOne) {
let mut runnable = runnable.clone();

let replaced_args: Vec<_> = runnable
.args
.iter()
.map(|arg| arg.replace("{test_id}", &test_id.to_string()))
.map(|arg| arg.replace("{label}", &self.label))
.collect();
runnable.args = replaced_args;

return Some(runnable);
}
}

None
self.find_replace_runnable(project_json::RunnableKind::Run, &|this, arg| {
arg.replace("{label}", &this.label).replace("{test_id}", &test_id.to_string())
})
}
RunnableKind::TestMod { path } => self
.find_replace_runnable(project_json::RunnableKind::TestMod, &|this, arg| {
arg.replace("{label}", &this.label).replace("{test_pattern}", path)
}),
RunnableKind::Bench { test_id } => {
self.find_replace_runnable(project_json::RunnableKind::BenchOne, &|this, arg| {
arg.replace("{label}", &this.label).replace("{bench_id}", &test_id.to_string())
})
}
RunnableKind::DocTest { test_id } => {
self.find_replace_runnable(project_json::RunnableKind::DocTestOne, &|this, arg| {
arg.replace("{label}", &this.label).replace("{test_id}", &test_id.to_string())
})
}
RunnableKind::TestMod { .. } => None,
RunnableKind::Bench { .. } => None,
RunnableKind::DocTest { .. } => None,
}
}
}
Expand Down