aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src/project_json.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-24 14:52:07 +0100
committerAleksey Kladov <[email protected]>2020-06-24 15:16:52 +0100
commite6c61d5072e600372ba4a38ad8893af37aaa77e6 (patch)
treefd9b9d3295963b17f65d2a0960189adeae38c3a2 /crates/ra_project_model/src/project_json.rs
parenta07cad16ab6271809d30ecf723420b3e41ec42ef (diff)
Cleanup project.json deserialization
Diffstat (limited to 'crates/ra_project_model/src/project_json.rs')
-rw-r--r--crates/ra_project_model/src/project_json.rs140
1 files changed, 81 insertions, 59 deletions
diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs
index e663bb4d7..4b5dcd634 100644
--- a/crates/ra_project_model/src/project_json.rs
+++ b/crates/ra_project_model/src/project_json.rs
@@ -2,11 +2,15 @@
2 2
3use std::path::PathBuf; 3use std::path::PathBuf;
4 4
5use paths::{AbsPath, AbsPathBuf};
6use ra_cfg::CfgOptions;
7use ra_db::{CrateId, Dependency, Edition};
5use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
6use serde::Deserialize; 9use serde::Deserialize;
10use stdx::split_delim;
7 11
8/// Roots and crates that compose this Rust project. 12/// Roots and crates that compose this Rust project.
9#[derive(Clone, Debug, Deserialize)] 13#[derive(Clone, Debug)]
10pub struct ProjectJson { 14pub struct ProjectJson {
11 pub(crate) roots: Vec<Root>, 15 pub(crate) roots: Vec<Root>,
12 pub(crate) crates: Vec<Crate>, 16 pub(crate) crates: Vec<Crate>,
@@ -14,82 +18,100 @@ pub struct ProjectJson {
14 18
15/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in 19/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in
16/// all roots. Roots might be nested. 20/// all roots. Roots might be nested.
17#[derive(Clone, Debug, Deserialize)] 21#[derive(Clone, Debug)]
18#[serde(transparent)]
19pub struct Root { 22pub struct Root {
20 pub(crate) path: PathBuf, 23 pub(crate) path: AbsPathBuf,
21} 24}
22 25
23/// A crate points to the root module of a crate and lists the dependencies of the crate. This is 26/// A crate points to the root module of a crate and lists the dependencies of the crate. This is
24/// useful in creating the crate graph. 27/// useful in creating the crate graph.
25#[derive(Clone, Debug, Deserialize)] 28#[derive(Clone, Debug)]
26pub struct Crate { 29pub struct Crate {
27 pub(crate) root_module: PathBuf, 30 pub(crate) root_module: AbsPathBuf,
28 pub(crate) edition: Edition, 31 pub(crate) edition: Edition,
29 pub(crate) deps: Vec<Dep>, 32 pub(crate) deps: Vec<Dependency>,
33 pub(crate) cfg: CfgOptions,
34 pub(crate) out_dir: Option<AbsPathBuf>,
35 pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
36}
30 37
31 #[serde(default)] 38impl ProjectJson {
32 pub(crate) cfg: FxHashSet<String>, 39 pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
40 ProjectJson {
41 roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(),
42 crates: data
43 .crates
44 .into_iter()
45 .map(|crate_data| Crate {
46 root_module: base.join(crate_data.root_module),
47 edition: crate_data.edition.into(),
48 deps: crate_data
49 .deps
50 .into_iter()
51 .map(|dep_data| Dependency {
52 crate_id: CrateId(dep_data.krate as u32),
53 name: dep_data.name.into(),
54 })
55 .collect::<Vec<_>>(),
56 cfg: {
57 let mut cfg = CfgOptions::default();
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 }
66 cfg
67 },
68 out_dir: crate_data.out_dir.map(|it| base.join(it)),
69 proc_macro_dylib_path: crate_data.proc_macro_dylib_path.map(|it| base.join(it)),
70 })
71 .collect::<Vec<_>>(),
72 }
73 }
74}
33 75
34 pub(crate) out_dir: Option<PathBuf>, 76#[derive(Deserialize)]
35 pub(crate) proc_macro_dylib_path: Option<PathBuf>, 77pub struct ProjectJsonData {
78 roots: Vec<PathBuf>,
79 crates: Vec<CrateData>,
36} 80}
37 81
38#[derive(Clone, Copy, Debug, Deserialize)] 82#[derive(Deserialize)]
83struct CrateData {
84 root_module: PathBuf,
85 edition: EditionData,
86 deps: Vec<DepData>,
87 #[serde(default)]
88 cfg: FxHashSet<String>,
89 out_dir: Option<PathBuf>,
90 proc_macro_dylib_path: Option<PathBuf>,
91}
92
93#[derive(Deserialize)]
39#[serde(rename = "edition")] 94#[serde(rename = "edition")]
40pub enum Edition { 95enum EditionData {
41 #[serde(rename = "2015")] 96 #[serde(rename = "2015")]
42 Edition2015, 97 Edition2015,
43 #[serde(rename = "2018")] 98 #[serde(rename = "2018")]
44 Edition2018, 99 Edition2018,
45} 100}
46 101
47/// Identifies a crate by position in the crates array. 102impl From<EditionData> for Edition {
48#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)] 103 fn from(data: EditionData) -> Self {
49#[serde(transparent)] 104 match data {
50pub struct CrateId(pub usize); 105 EditionData::Edition2015 => Edition::Edition2015,
51 106 EditionData::Edition2018 => Edition::Edition2018,
52/// A dependency of a crate, identified by its id in the crates array and name. 107 }
53#[derive(Clone, Debug, Deserialize)] 108 }
54pub struct Dep {
55 #[serde(rename = "crate")]
56 pub(crate) krate: CrateId,
57 pub(crate) name: String,
58} 109}
59 110
60#[cfg(test)] 111#[derive(Deserialize)]
61mod tests { 112struct DepData {
62 use super::*; 113 /// Identifies a crate by position in the crates array.
63 use serde_json::json; 114 #[serde(rename = "crate")]
64 115 krate: usize,
65 #[test] 116 name: String,
66 fn test_crate_deserialization() {
67 let raw_json = json!( {
68 "crate_id": 2,
69 "root_module": "this/is/a/file/path.rs",
70 "deps": [
71 {
72 "crate": 1,
73 "name": "some_dep_crate"
74 },
75 ],
76 "edition": "2015",
77 "cfg": [
78 "atom_1",
79 "atom_2",
80 "feature=feature_1",
81 "feature=feature_2",
82 "other=value",
83 ],
84
85 });
86
87 let krate: Crate = serde_json::from_value(raw_json).unwrap();
88
89 assert!(krate.cfg.contains(&"atom_1".to_string()));
90 assert!(krate.cfg.contains(&"atom_2".to_string()));
91 assert!(krate.cfg.contains(&"feature=feature_1".to_string()));
92 assert!(krate.cfg.contains(&"feature=feature_2".to_string()));
93 assert!(krate.cfg.contains(&"other=value".to_string()));
94 }
95} 117}