diff options
Diffstat (limited to 'crates/ra_project_model/src/project_json.rs')
-rw-r--r-- | crates/ra_project_model/src/project_json.rs | 118 |
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 @@ | |||
3 | use std::path::PathBuf; | 3 | use std::path::PathBuf; |
4 | 4 | ||
5 | use paths::{AbsPath, AbsPathBuf}; | 5 | use paths::{AbsPath, AbsPathBuf}; |
6 | use ra_cfg::CfgOptions; | 6 | use ra_db::{CrateId, CrateName, Dependency, Edition}; |
7 | use ra_db::{CrateId, Dependency, Edition}; | 7 | use rustc_hash::FxHashMap; |
8 | use rustc_hash::FxHashSet; | 8 | use serde::{de, Deserialize}; |
9 | use serde::Deserialize; | 9 | |
10 | use stdx::split_delim; | 10 | use 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)] |
14 | pub struct ProjectJson { | 14 | pub 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)] | ||
22 | pub 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)] |
29 | pub struct Crate { | 21 | pub 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 | ||
38 | impl ProjectJson { | 34 | impl 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)] |
77 | pub struct ProjectJsonData { | 85 | pub 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)] | ||
132 | struct CrateSource { | ||
133 | include_dirs: Vec<PathBuf>, | ||
134 | exclude_dirs: Vec<PathBuf>, | ||
135 | } | ||
136 | |||
137 | fn deserialize_crate_name<'de, D>(de: D) -> Result<CrateName, D::Error> | ||
138 | where | ||
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 | } |