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.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs
new file mode 100644
index 000000000..4b5dcd634
--- /dev/null
+++ b/crates/ra_project_model/src/project_json.rs
@@ -0,0 +1,117 @@
1//! FIXME: write short doc here
2
3use std::path::PathBuf;
4
5use paths::{AbsPath, AbsPathBuf};
6use ra_cfg::CfgOptions;
7use ra_db::{CrateId, Dependency, Edition};
8use rustc_hash::FxHashSet;
9use serde::Deserialize;
10use stdx::split_delim;
11
12/// Roots and crates that compose this Rust project.
13#[derive(Clone, Debug)]
14pub struct ProjectJson {
15 pub(crate) roots: Vec<Root>,
16 pub(crate) crates: Vec<Crate>,
17}
18
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
27/// useful in creating the crate graph.
28#[derive(Clone, Debug)]
29pub struct Crate {
30 pub(crate) root_module: AbsPathBuf,
31 pub(crate) edition: Edition,
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}
37
38impl ProjectJson {
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}
75
76#[derive(Deserialize)]
77pub struct ProjectJsonData {
78 roots: Vec<PathBuf>,
79 crates: Vec<CrateData>,
80}
81
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)]
94#[serde(rename = "edition")]
95enum EditionData {
96 #[serde(rename = "2015")]
97 Edition2015,
98 #[serde(rename = "2018")]
99 Edition2018,
100}
101
102impl From<EditionData> for Edition {
103 fn from(data: EditionData) -> Self {
104 match data {
105 EditionData::Edition2015 => Edition::Edition2015,
106 EditionData::Edition2018 => Edition::Edition2018,
107 }
108 }
109}
110
111#[derive(Deserialize)]
112struct DepData {
113 /// Identifies a crate by position in the crates array.
114 #[serde(rename = "crate")]
115 krate: usize,
116 name: String,
117}