aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src/project_json.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_project_model/src/project_json.rs')
-rw-r--r--crates/ra_project_model/src/project_json.rs118
1 files changed, 72 insertions, 46 deletions
diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs
index 4b5dcd634..e3f3163f6 100644
--- a/crates/ra_project_model/src/project_json.rs
+++ b/crates/ra_project_model/src/project_json.rs
@@ -3,70 +3,78 @@
3use std::path::PathBuf; 3use std::path::PathBuf;
4 4
5use paths::{AbsPath, AbsPathBuf}; 5use paths::{AbsPath, AbsPathBuf};
6use ra_cfg::CfgOptions; 6use ra_db::{CrateId, CrateName, Dependency, Edition};
7use ra_db::{CrateId, Dependency, Edition}; 7use rustc_hash::FxHashMap;
8use rustc_hash::FxHashSet; 8use serde::{de, Deserialize};
9use serde::Deserialize; 9
10use stdx::split_delim; 10use crate::cfg_flag::CfgFlag;
11 11
12/// Roots and crates that compose this Rust project. 12/// Roots and crates that compose this Rust project.
13#[derive(Clone, Debug)] 13#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct ProjectJson { 14pub struct ProjectJson {
15 pub(crate) roots: Vec<Root>,
16 pub(crate) crates: Vec<Crate>, 15 pub(crate) crates: Vec<Crate>,
17} 16}
18 17
19/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in
20/// all roots. Roots might be nested.
21#[derive(Clone, Debug)]
22pub struct Root {
23 pub(crate) path: AbsPathBuf,
24}
25
26/// A crate points to the root module of a crate and lists the dependencies of the crate. This is 18/// A crate points to the root module of a crate and lists the dependencies of the crate. This is
27/// useful in creating the crate graph. 19/// useful in creating the crate graph.
28#[derive(Clone, Debug)] 20#[derive(Clone, Debug, Eq, PartialEq)]
29pub struct Crate { 21pub struct Crate {
30 pub(crate) root_module: AbsPathBuf, 22 pub(crate) root_module: AbsPathBuf,
31 pub(crate) edition: Edition, 23 pub(crate) edition: Edition,
32 pub(crate) deps: Vec<Dependency>, 24 pub(crate) deps: Vec<Dependency>,
33 pub(crate) cfg: CfgOptions, 25 pub(crate) cfg: Vec<CfgFlag>,
34 pub(crate) out_dir: Option<AbsPathBuf>, 26 pub(crate) target: Option<String>,
27 pub(crate) env: FxHashMap<String, String>,
35 pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, 28 pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
29 pub(crate) is_workspace_member: bool,
30 pub(crate) include: Vec<AbsPathBuf>,
31 pub(crate) exclude: Vec<AbsPathBuf>,
36} 32}
37 33
38impl ProjectJson { 34impl ProjectJson {
39 pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { 35 pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
40 ProjectJson { 36 ProjectJson {
41 roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(),
42 crates: data 37 crates: data
43 .crates 38 .crates
44 .into_iter() 39 .into_iter()
45 .map(|crate_data| Crate { 40 .map(|crate_data| {
46 root_module: base.join(crate_data.root_module), 41 let is_workspace_member = crate_data.is_workspace_member.unwrap_or_else(|| {
47 edition: crate_data.edition.into(), 42 crate_data.root_module.is_relative()
48 deps: crate_data 43 && !crate_data.root_module.starts_with("..")
49 .deps 44 || crate_data.root_module.starts_with(base)
50 .into_iter() 45 });
51 .map(|dep_data| Dependency { 46 let root_module = base.join(crate_data.root_module);
52 crate_id: CrateId(dep_data.krate as u32), 47 let (include, exclude) = match crate_data.source {
53 name: dep_data.name.into(), 48 Some(src) => {
54 }) 49 let absolutize = |dirs: Vec<PathBuf>| {
55 .collect::<Vec<_>>(), 50 dirs.into_iter().map(|it| base.join(it)).collect::<Vec<_>>()
56 cfg: { 51 };
57 let mut cfg = CfgOptions::default(); 52 (absolutize(src.include_dirs), absolutize(src.exclude_dirs))
58 for entry in &crate_data.cfg {
59 match split_delim(entry, '=') {
60 Some((key, value)) => {
61 cfg.insert_key_value(key.into(), value.into());
62 }
63 None => cfg.insert_atom(entry.into()),
64 }
65 } 53 }
66 cfg 54 None => (vec![root_module.parent().unwrap().to_path_buf()], Vec::new()),
67 }, 55 };
68 out_dir: crate_data.out_dir.map(|it| base.join(it)), 56
69 proc_macro_dylib_path: crate_data.proc_macro_dylib_path.map(|it| base.join(it)), 57 Crate {
58 root_module,
59 edition: crate_data.edition.into(),
60 deps: crate_data
61 .deps
62 .into_iter()
63 .map(|dep_data| Dependency {
64 crate_id: CrateId(dep_data.krate as u32),
65 name: dep_data.name,
66 })
67 .collect::<Vec<_>>(),
68 cfg: crate_data.cfg,
69 target: crate_data.target,
70 env: crate_data.env,
71 proc_macro_dylib_path: crate_data
72 .proc_macro_dylib_path
73 .map(|it| base.join(it)),
74 is_workspace_member,
75 include,
76 exclude,
77 }
70 }) 78 })
71 .collect::<Vec<_>>(), 79 .collect::<Vec<_>>(),
72 } 80 }
@@ -75,7 +83,6 @@ impl ProjectJson {
75 83
76#[derive(Deserialize)] 84#[derive(Deserialize)]
77pub struct ProjectJsonData { 85pub struct ProjectJsonData {
78 roots: Vec<PathBuf>,
79 crates: Vec<CrateData>, 86 crates: Vec<CrateData>,
80} 87}
81 88
@@ -85,9 +92,13 @@ struct CrateData {
85 edition: EditionData, 92 edition: EditionData,
86 deps: Vec<DepData>, 93 deps: Vec<DepData>,
87 #[serde(default)] 94 #[serde(default)]
88 cfg: FxHashSet<String>, 95 cfg: Vec<CfgFlag>,
89 out_dir: Option<PathBuf>, 96 target: Option<String>,
97 #[serde(default)]
98 env: FxHashMap<String, String>,
90 proc_macro_dylib_path: Option<PathBuf>, 99 proc_macro_dylib_path: Option<PathBuf>,
100 is_workspace_member: Option<bool>,
101 source: Option<CrateSource>,
91} 102}
92 103
93#[derive(Deserialize)] 104#[derive(Deserialize)]
@@ -113,5 +124,20 @@ struct DepData {
113 /// Identifies a crate by position in the crates array. 124 /// Identifies a crate by position in the crates array.
114 #[serde(rename = "crate")] 125 #[serde(rename = "crate")]
115 krate: usize, 126 krate: usize,
116 name: String, 127 #[serde(deserialize_with = "deserialize_crate_name")]
128 name: CrateName,
129}
130
131#[derive(Deserialize)]
132struct CrateSource {
133 include_dirs: Vec<PathBuf>,
134 exclude_dirs: Vec<PathBuf>,
135}
136
137fn deserialize_crate_name<'de, D>(de: D) -> Result<CrateName, D::Error>
138where
139 D: de::Deserializer<'de>,
140{
141 let name = String::deserialize(de)?;
142 CrateName::new(&name).map_err(|err| de::Error::custom(format!("invalid crate name: {:?}", err)))
117} 143}