Skip to content

Commit

Permalink
Extend TargetSpec functionality to rust-project.json
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbarsky authored and Wilfred committed Mar 28, 2024
1 parent 4b33850 commit 843626e
Show file tree
Hide file tree
Showing 15 changed files with 532 additions and 238 deletions.
6 changes: 2 additions & 4 deletions crates/ide/src/runnables.rs
Expand Up @@ -65,15 +65,13 @@ enum RunnableTestKind {

impl Runnable {
// test package::module::testname
pub fn label(&self, target: Option<String>) -> String {
pub fn label(&self, target: String) -> String {
match &self.kind {
RunnableKind::Test { test_id, .. } => format!("test {test_id}"),
RunnableKind::TestMod { path } => format!("test-mod {path}"),
RunnableKind::Bench { test_id } => format!("bench {test_id}"),
RunnableKind::DocTest { test_id, .. } => format!("doctest {test_id}"),
RunnableKind::Bin => {
target.map_or_else(|| "run binary".to_owned(), |t| format!("run {t}"))
}
RunnableKind::Bin => target,
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/project-model/src/lib.rs
Expand Up @@ -21,7 +21,7 @@ mod build_scripts;
mod cargo_workspace;
mod cfg_flag;
mod manifest_path;
mod project_json;
pub mod project_json;
mod rustc_cfg;
mod sysroot;
pub mod target_data_layout;
Expand Down
121 changes: 106 additions & 15 deletions crates/project-model/src/project_json.rs
Expand Up @@ -56,7 +56,7 @@ use rustc_hash::FxHashMap;
use serde::{de, Deserialize};
use span::Edition;

use crate::cfg_flag::CfgFlag;
use crate::{cfg_flag::CfgFlag, TargetKind};

/// Roots and crates that compose this Rust project.
#[derive(Clone, Debug, Eq, PartialEq)]
Expand All @@ -73,20 +73,37 @@ pub struct ProjectJson {
/// useful in creating the crate graph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Crate {
pub(crate) display_name: Option<CrateDisplayName>,
pub(crate) root_module: AbsPathBuf,
pub(crate) edition: Edition,
pub(crate) version: Option<String>,
pub(crate) deps: Vec<Dependency>,
pub(crate) cfg: Vec<CfgFlag>,
pub(crate) target: Option<String>,
pub(crate) env: FxHashMap<String, String>,
pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
pub(crate) is_workspace_member: bool,
pub(crate) include: Vec<AbsPathBuf>,
pub(crate) exclude: Vec<AbsPathBuf>,
pub(crate) is_proc_macro: bool,
pub(crate) repository: Option<String>,
pub display_name: Option<CrateDisplayName>,
pub root_module: AbsPathBuf,
pub edition: Edition,
pub version: Option<String>,
pub deps: Vec<Dependency>,
pub cfg: Vec<CfgFlag>,
pub target: Option<String>,
pub env: FxHashMap<String, String>,
pub proc_macro_dylib_path: Option<AbsPathBuf>,
pub is_workspace_member: bool,
pub include: Vec<AbsPathBuf>,
pub exclude: Vec<AbsPathBuf>,
pub is_proc_macro: bool,
pub repository: Option<String>,
pub target_spec: Option<TargetSpec>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TargetSpec {
pub manifest_file: AbsPathBuf,
pub target_label: String,
pub target_kind: TargetKind,
pub runnables: Runnables,
pub flycheck_command: Vec<String>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Runnables {
pub check: Vec<String>,
pub run: Vec<String>,
pub test: Vec<String>,
}

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

let target_spec = match crate_data.target_spec {
Some(spec) => {
let spec = TargetSpec {
manifest_file: absolutize_on_base(spec.manifest_file),
target_label: spec.target_label,
target_kind: spec.target_kind.into(),
runnables: spec.runnables.into(),
flycheck_command: spec.flycheck_command,
};
Some(spec)
}
None => None,
};

Crate {
display_name: crate_data
.display_name
Expand Down Expand Up @@ -149,6 +180,7 @@ impl ProjectJson {
exclude,
is_proc_macro: crate_data.is_proc_macro,
repository: crate_data.repository,
target_spec,
}
})
.collect(),
Expand All @@ -172,6 +204,14 @@ impl ProjectJson {
pub fn path(&self) -> &AbsPath {
&self.project_root
}

pub fn crate_by_root(&self, root: &AbsPath) -> Option<Crate> {
self.crates
.iter()
.filter(|krate| krate.is_workspace_member)
.find(|krate| &krate.root_module == root)
.cloned()
}
}

#[derive(Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -201,6 +241,8 @@ struct CrateData {
is_proc_macro: bool,
#[serde(default)]
repository: Option<String>,
#[serde(default)]
target_spec: Option<TargetSpecData>,
}

#[derive(Deserialize, Debug, Clone)]
Expand All @@ -216,6 +258,55 @@ enum EditionData {
Edition2024,
}

#[derive(Deserialize, Debug, Clone)]
pub struct TargetSpecData {
manifest_file: Utf8PathBuf,
target_label: String,
target_kind: TargetKindData,
runnables: RunnablesData,
flycheck_command: Vec<String>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct RunnablesData {
check: Vec<String>,
run: Vec<String>,
test: Vec<String>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TargetKindData {
Bin,
/// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
Lib,
Example,
Test,
Bench,
BuildScript,
Other,
}

impl From<TargetKindData> for TargetKind {
fn from(value: TargetKindData) -> Self {
match value {
TargetKindData::Bin => TargetKind::Bin,
TargetKindData::Lib => TargetKind::Lib { is_proc_macro: false },
TargetKindData::Example => TargetKind::Example,
TargetKindData::Test => TargetKind::Test,
TargetKindData::Bench => TargetKind::Bench,
TargetKindData::BuildScript => TargetKind::BuildScript,
TargetKindData::Other => TargetKind::Other,
}
}
}

impl From<RunnablesData> for Runnables {
fn from(value: RunnablesData) -> Self {
Runnables { check: value.check, run: value.run, test: value.test }
}
}

impl From<EditionData> for Edition {
fn from(data: EditionData) -> Self {
match data {
Expand Down
17 changes: 12 additions & 5 deletions crates/rust-analyzer/src/global_state.rs
Expand Up @@ -18,7 +18,7 @@ use parking_lot::{
RwLockWriteGuard,
};
use proc_macro_api::ProcMacroServer;
use project_model::{CargoWorkspace, ProjectWorkspace, Target, WorkspaceBuildScripts};
use project_model::{CargoWorkspace, ProjectJson, ProjectWorkspace, Target, WorkspaceBuildScripts};
use rustc_hash::{FxHashMap, FxHashSet};
use triomphe::Arc;
use vfs::{AnchoredPathBuf, ChangedFile, Vfs};
Expand Down Expand Up @@ -502,18 +502,20 @@ impl GlobalStateSnapshot {
self.vfs_read().file_path(file_id).clone()
}

pub(crate) fn cargo_target_for_crate_root(
pub(crate) fn target_for_crate_root(
&self,
crate_id: CrateId,
) -> Option<(&CargoWorkspace, Target)> {
) -> Option<TargetForCrateRoot<'_>> {
let file_id = self.analysis.crate_root(crate_id).ok()?;
let path = self.vfs_read().file_path(file_id).clone();
let path = path.as_path()?;
self.workspaces.iter().find_map(|ws| match ws {
ProjectWorkspace::Cargo { cargo, .. } => {
cargo.target_by_root(path).map(|it| (cargo, it))
cargo.target_by_root(path).map(|it| TargetForCrateRoot::Cargo(cargo, it))
}
ProjectWorkspace::Json { project, .. } => {
project.crate_by_root(path).map(|it| TargetForCrateRoot::JsonProject(project, it))
}
ProjectWorkspace::Json { .. } => None,
ProjectWorkspace::DetachedFiles { .. } => None,
})
}
Expand All @@ -523,6 +525,11 @@ impl GlobalStateSnapshot {
}
}

pub(crate) enum TargetForCrateRoot<'a> {
Cargo(&'a CargoWorkspace, Target),
JsonProject(&'a ProjectJson, project_model::project_json::Crate),

Check failure on line 530 in crates/rust-analyzer/src/global_state.rs

View workflow job for this annotation

GitHub Actions / Rust (ubuntu-latest)

field `0` is never read
}

pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
let path = vfs.file_path(id);
let path = path.as_path().unwrap();
Expand Down

0 comments on commit 843626e

Please sign in to comment.