Skip to content

Commit 20733f6

Browse files
committed
Extend TargetSpec functionality to rust-project.json
1 parent 21b06c1 commit 20733f6

File tree

16 files changed

+530
-228
lines changed

16 files changed

+530
-228
lines changed

crates/ide/src/runnables.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,13 @@ enum RunnableTestKind {
6565

6666
impl Runnable {
6767
// test package::module::testname
68-
pub fn label(&self, target: Option<String>) -> String {
68+
pub fn label(&self, target: String) -> String {
6969
match &self.kind {
7070
RunnableKind::Test { test_id, .. } => format!("test {test_id}"),
7171
RunnableKind::TestMod { path } => format!("test-mod {path}"),
7272
RunnableKind::Bench { test_id } => format!("bench {test_id}"),
7373
RunnableKind::DocTest { test_id, .. } => format!("doctest {test_id}"),
74-
RunnableKind::Bin => {
75-
target.map_or_else(|| "run binary".to_string(), |t| format!("run {t}"))
76-
}
74+
RunnableKind::Bin => target,
7775
}
7876
}
7977

crates/project-model/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
mod manifest_path;
2121
mod cargo_workspace;
2222
mod cfg_flag;
23-
mod project_json;
23+
pub mod project_json;
2424
mod sysroot;
2525
mod workspace;
2626
mod rustc_cfg;

crates/project-model/src/project_json.rs

Lines changed: 107 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use rustc_hash::FxHashMap;
5656
use serde::{de, Deserialize};
5757
use std::path::PathBuf;
5858

59-
use crate::cfg_flag::CfgFlag;
59+
use crate::{cfg_flag::CfgFlag, TargetKind};
6060

6161
/// Roots and crates that compose this Rust project.
6262
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -73,20 +73,37 @@ pub struct ProjectJson {
7373
/// useful in creating the crate graph.
7474
#[derive(Clone, Debug, Eq, PartialEq)]
7575
pub struct Crate {
76-
pub(crate) display_name: Option<CrateDisplayName>,
77-
pub(crate) root_module: AbsPathBuf,
78-
pub(crate) edition: Edition,
79-
pub(crate) version: Option<String>,
80-
pub(crate) deps: Vec<Dependency>,
81-
pub(crate) cfg: Vec<CfgFlag>,
82-
pub(crate) target: Option<String>,
83-
pub(crate) env: FxHashMap<String, String>,
84-
pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
85-
pub(crate) is_workspace_member: bool,
86-
pub(crate) include: Vec<AbsPathBuf>,
87-
pub(crate) exclude: Vec<AbsPathBuf>,
88-
pub(crate) is_proc_macro: bool,
89-
pub(crate) repository: Option<String>,
76+
pub display_name: Option<CrateDisplayName>,
77+
pub root_module: AbsPathBuf,
78+
pub edition: Edition,
79+
pub version: Option<String>,
80+
pub deps: Vec<Dependency>,
81+
pub cfg: Vec<CfgFlag>,
82+
pub target: Option<String>,
83+
pub env: FxHashMap<String, String>,
84+
pub proc_macro_dylib_path: Option<AbsPathBuf>,
85+
pub is_workspace_member: bool,
86+
pub include: Vec<AbsPathBuf>,
87+
pub exclude: Vec<AbsPathBuf>,
88+
pub is_proc_macro: bool,
89+
pub repository: Option<String>,
90+
pub target_spec: Option<TargetSpec>,
91+
}
92+
93+
#[derive(Clone, Debug, Eq, PartialEq)]
94+
pub struct TargetSpec {
95+
pub manifest_file: AbsPathBuf,
96+
pub target_label: String,
97+
pub target_kind: TargetKind,
98+
pub runnables: Runnables,
99+
pub flycheck_command: Vec<String>,
100+
}
101+
102+
#[derive(Clone, Debug, Eq, PartialEq)]
103+
pub struct Runnables {
104+
pub check: Vec<String>,
105+
pub run: Vec<String>,
106+
pub test: Vec<String>,
90107
}
91108

92109
impl ProjectJson {
@@ -121,6 +138,20 @@ impl ProjectJson {
121138
None => (vec![root_module.parent().unwrap().to_path_buf()], Vec::new()),
122139
};
123140

141+
let target_spec = match crate_data.target_spec {
142+
Some(spec) => {
143+
let spec = TargetSpec {
144+
manifest_file: absolutize_on_base(spec.manifest_file),
145+
target_label: spec.target_label,
146+
target_kind: spec.target_kind.into(),
147+
runnables: spec.runnables.into(),
148+
flycheck_command: spec.flycheck_command,
149+
};
150+
Some(spec)
151+
}
152+
None => None,
153+
};
154+
124155
Crate {
125156
display_name: crate_data
126157
.display_name
@@ -150,6 +181,7 @@ impl ProjectJson {
150181
exclude,
151182
is_proc_macro: crate_data.is_proc_macro,
152183
repository: crate_data.repository,
184+
target_spec,
153185
}
154186
})
155187
.collect(),
@@ -173,6 +205,15 @@ impl ProjectJson {
173205
pub fn path(&self) -> &AbsPath {
174206
&self.project_root
175207
}
208+
209+
pub fn crate_by_root(&self, root: &AbsPath) -> Option<Crate> {
210+
self.crates
211+
.iter()
212+
.filter(|krate| krate.is_workspace_member)
213+
.find(|krate| &krate.root_module == root)
214+
.map(|krate| krate)
215+
.cloned()
216+
}
176217
}
177218

178219
#[derive(Deserialize, Debug, Clone)]
@@ -202,6 +243,8 @@ struct CrateData {
202243
is_proc_macro: bool,
203244
#[serde(default)]
204245
repository: Option<String>,
246+
#[serde(default)]
247+
target_spec: Option<TargetSpecData>,
205248
}
206249

207250
#[derive(Deserialize, Debug, Clone)]
@@ -215,6 +258,55 @@ enum EditionData {
215258
Edition2021,
216259
}
217260

261+
#[derive(Deserialize, Debug, Clone)]
262+
pub struct TargetSpecData {
263+
manifest_file: PathBuf,
264+
target_label: String,
265+
target_kind: TargetKindData,
266+
runnables: RunnablesData,
267+
flycheck_command: Vec<String>,
268+
}
269+
270+
#[derive(Deserialize, Debug, Clone)]
271+
pub struct RunnablesData {
272+
check: Vec<String>,
273+
run: Vec<String>,
274+
test: Vec<String>,
275+
}
276+
277+
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
278+
#[serde(rename_all = "camelCase")]
279+
pub enum TargetKindData {
280+
Bin,
281+
/// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
282+
Lib,
283+
Example,
284+
Test,
285+
Bench,
286+
BuildScript,
287+
Other,
288+
}
289+
290+
impl From<TargetKindData> for TargetKind {
291+
fn from(value: TargetKindData) -> Self {
292+
match value {
293+
TargetKindData::Bin => TargetKind::Bin,
294+
TargetKindData::Lib => TargetKind::Lib,
295+
TargetKindData::Example => TargetKind::Example,
296+
TargetKindData::Test => TargetKind::Test,
297+
TargetKindData::Bench => TargetKind::Bench,
298+
TargetKindData::BuildScript => TargetKind::BuildScript,
299+
TargetKindData::Other => TargetKind::Other,
300+
}
301+
}
302+
}
303+
304+
impl From<RunnablesData> for Runnables {
305+
fn from(value: RunnablesData) -> Self {
306+
Runnables { check: value.check, run: value.run, test: value.test }
307+
}
308+
}
309+
218310
impl From<EditionData> for Edition {
219311
fn from(data: EditionData) -> Self {
220312
match data {

crates/rust-analyzer/src/global_state.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use parking_lot::{
1717
RwLockWriteGuard,
1818
};
1919
use proc_macro_api::ProcMacroServer;
20-
use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
20+
use project_model::{CargoWorkspace, ProjectJson, ProjectWorkspace, Target, WorkspaceBuildScripts};
2121
use rustc_hash::{FxHashMap, FxHashSet};
2222
use triomphe::Arc;
2323
use vfs::{AnchoredPathBuf, Vfs};
@@ -477,18 +477,20 @@ impl GlobalStateSnapshot {
477477
self.vfs_read().file_path(file_id)
478478
}
479479

480-
pub(crate) fn cargo_target_for_crate_root(
480+
pub(crate) fn target_for_crate_root(
481481
&self,
482482
crate_id: CrateId,
483-
) -> Option<(&CargoWorkspace, Target)> {
483+
) -> Option<TargetForCrateRoot<'_>> {
484484
let file_id = self.analysis.crate_root(crate_id).ok()?;
485485
let path = self.vfs_read().file_path(file_id);
486486
let path = path.as_path()?;
487487
self.workspaces.iter().find_map(|ws| match ws {
488488
ProjectWorkspace::Cargo { cargo, .. } => {
489-
cargo.target_by_root(path).map(|it| (cargo, it))
489+
cargo.target_by_root(path).map(|it| TargetForCrateRoot::Cargo(cargo, it))
490+
}
491+
ProjectWorkspace::Json { project, .. } => {
492+
project.crate_by_root(path).map(|it| TargetForCrateRoot::JsonProject(project, it))
490493
}
491-
ProjectWorkspace::Json { .. } => None,
492494
ProjectWorkspace::DetachedFiles { .. } => None,
493495
})
494496
}
@@ -502,6 +504,11 @@ impl GlobalStateSnapshot {
502504
}
503505
}
504506

507+
pub(crate) enum TargetForCrateRoot<'a> {
508+
Cargo(&'a CargoWorkspace, Target),
509+
JsonProject(&'a ProjectJson, project_model::project_json::Crate),
510+
}
511+
505512
pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
506513
let path = vfs.file_path(id);
507514
let path = path.as_path().unwrap();

0 commit comments

Comments
 (0)