Skip to content

Commit 8903c89

Browse files
committed
Extend TargetSpec functionality to rust-project.json
1 parent 831d0e0 commit 8903c89

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)]
@@ -217,6 +260,55 @@ enum EditionData {
217260
Edition2024,
218261
}
219262

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

crates/rust-analyzer/src/global_state.rs

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

481-
pub(crate) fn cargo_target_for_crate_root(
481+
pub(crate) fn target_for_crate_root(
482482
&self,
483483
crate_id: CrateId,
484-
) -> Option<(&CargoWorkspace, Target)> {
484+
) -> Option<TargetForCrateRoot<'_>> {
485485
let file_id = self.analysis.crate_root(crate_id).ok()?;
486486
let path = self.vfs_read().file_path(file_id);
487487
let path = path.as_path()?;
488488
self.workspaces.iter().find_map(|ws| match ws {
489489
ProjectWorkspace::Cargo { cargo, .. } => {
490-
cargo.target_by_root(path).map(|it| (cargo, it))
490+
cargo.target_by_root(path).map(|it| TargetForCrateRoot::Cargo(cargo, it))
491+
}
492+
ProjectWorkspace::Json { project, .. } => {
493+
project.crate_by_root(path).map(|it| TargetForCrateRoot::JsonProject(project, it))
491494
}
492-
ProjectWorkspace::Json { .. } => None,
493495
ProjectWorkspace::DetachedFiles { .. } => None,
494496
})
495497
}
@@ -503,6 +505,11 @@ impl GlobalStateSnapshot {
503505
}
504506
}
505507

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

0 commit comments

Comments
 (0)