diff options
Diffstat (limited to 'crates/ra_project_model')
-rw-r--r-- | crates/ra_project_model/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 8 | ||||
-rw-r--r-- | crates/ra_project_model/src/json_project.rs | 5 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 57 | ||||
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 2 |
5 files changed, 70 insertions, 3 deletions
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index ae6b91aa6..a65100031 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml | |||
@@ -12,6 +12,7 @@ cargo_metadata = "0.8.2" | |||
12 | 12 | ||
13 | ra_arena = { path = "../ra_arena" } | 13 | ra_arena = { path = "../ra_arena" } |
14 | ra_db = { path = "../ra_db" } | 14 | ra_db = { path = "../ra_db" } |
15 | ra_cfg = { path = "../ra_cfg" } | ||
15 | 16 | ||
16 | serde = { version = "1.0.89", features = ["derive"] } | 17 | serde = { version = "1.0.89", features = ["derive"] } |
17 | serde_json = "1.0.39" | 18 | serde_json = "1.0.39" |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 712d8818f..28dadea9d 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | use std::path::{Path, PathBuf}; | 3 | use std::path::{Path, PathBuf}; |
2 | 4 | ||
3 | use cargo_metadata::{CargoOpt, MetadataCommand}; | 5 | use cargo_metadata::{CargoOpt, MetadataCommand}; |
@@ -37,6 +39,7 @@ struct PackageData { | |||
37 | is_member: bool, | 39 | is_member: bool, |
38 | dependencies: Vec<PackageDependency>, | 40 | dependencies: Vec<PackageDependency>, |
39 | edition: Edition, | 41 | edition: Edition, |
42 | features: Vec<String>, | ||
40 | } | 43 | } |
41 | 44 | ||
42 | #[derive(Debug, Clone)] | 45 | #[derive(Debug, Clone)] |
@@ -89,6 +92,9 @@ impl Package { | |||
89 | pub fn edition(self, ws: &CargoWorkspace) -> Edition { | 92 | pub fn edition(self, ws: &CargoWorkspace) -> Edition { |
90 | ws.packages[self].edition | 93 | ws.packages[self].edition |
91 | } | 94 | } |
95 | pub fn features(self, ws: &CargoWorkspace) -> &[String] { | ||
96 | &ws.packages[self].features | ||
97 | } | ||
92 | pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a { | 98 | pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a { |
93 | ws.packages[self].targets.iter().cloned() | 99 | ws.packages[self].targets.iter().cloned() |
94 | } | 100 | } |
@@ -142,6 +148,7 @@ impl CargoWorkspace { | |||
142 | is_member, | 148 | is_member, |
143 | edition: Edition::from_string(&meta_pkg.edition), | 149 | edition: Edition::from_string(&meta_pkg.edition), |
144 | dependencies: Vec::new(), | 150 | dependencies: Vec::new(), |
151 | features: Vec::new(), | ||
145 | }); | 152 | }); |
146 | let pkg_data = &mut packages[pkg]; | 153 | let pkg_data = &mut packages[pkg]; |
147 | pkg_by_id.insert(meta_pkg.id.clone(), pkg); | 154 | pkg_by_id.insert(meta_pkg.id.clone(), pkg); |
@@ -162,6 +169,7 @@ impl CargoWorkspace { | |||
162 | let dep = PackageDependency { name: dep_node.name, pkg: pkg_by_id[&dep_node.pkg] }; | 169 | let dep = PackageDependency { name: dep_node.name, pkg: pkg_by_id[&dep_node.pkg] }; |
163 | packages[source].dependencies.push(dep); | 170 | packages[source].dependencies.push(dep); |
164 | } | 171 | } |
172 | packages[source].features.extend(node.features); | ||
165 | } | 173 | } |
166 | 174 | ||
167 | Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root }) | 175 | Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root }) |
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs index 9a9eb9e1f..1bacb1d09 100644 --- a/crates/ra_project_model/src/json_project.rs +++ b/crates/ra_project_model/src/json_project.rs | |||
@@ -1,5 +1,8 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | use std::path::PathBuf; | 3 | use std::path::PathBuf; |
2 | 4 | ||
5 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
3 | use serde::Deserialize; | 6 | use serde::Deserialize; |
4 | 7 | ||
5 | /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in | 8 | /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in |
@@ -17,6 +20,8 @@ pub struct Crate { | |||
17 | pub(crate) root_module: PathBuf, | 20 | pub(crate) root_module: PathBuf, |
18 | pub(crate) edition: Edition, | 21 | pub(crate) edition: Edition, |
19 | pub(crate) deps: Vec<Dep>, | 22 | pub(crate) deps: Vec<Dep>, |
23 | pub(crate) atom_cfgs: FxHashSet<String>, | ||
24 | pub(crate) key_value_cfgs: FxHashMap<String, String>, | ||
20 | } | 25 | } |
21 | 26 | ||
22 | #[derive(Clone, Copy, Debug, Deserialize)] | 27 | #[derive(Clone, Copy, Debug, Deserialize)] |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 4fa32dc34..640a5ebd3 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | mod cargo_workspace; | 3 | mod cargo_workspace; |
2 | mod json_project; | 4 | mod json_project; |
3 | mod sysroot; | 5 | mod sysroot; |
@@ -7,8 +9,10 @@ use std::{ | |||
7 | fs::File, | 9 | fs::File, |
8 | io::BufReader, | 10 | io::BufReader, |
9 | path::{Path, PathBuf}, | 11 | path::{Path, PathBuf}, |
12 | process::Command, | ||
10 | }; | 13 | }; |
11 | 14 | ||
15 | use ra_cfg::CfgOptions; | ||
12 | use ra_db::{CrateGraph, CrateId, Edition, FileId}; | 16 | use ra_db::{CrateGraph, CrateId, Edition, FileId}; |
13 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
14 | use serde_json::from_reader; | 18 | use serde_json::from_reader; |
@@ -115,6 +119,7 @@ impl ProjectWorkspace { | |||
115 | 119 | ||
116 | pub fn to_crate_graph( | 120 | pub fn to_crate_graph( |
117 | &self, | 121 | &self, |
122 | default_cfg_options: &CfgOptions, | ||
118 | load: &mut dyn FnMut(&Path) -> Option<FileId>, | 123 | load: &mut dyn FnMut(&Path) -> Option<FileId>, |
119 | ) -> (CrateGraph, FxHashMap<CrateId, String>) { | 124 | ) -> (CrateGraph, FxHashMap<CrateId, String>) { |
120 | let mut crate_graph = CrateGraph::default(); | 125 | let mut crate_graph = CrateGraph::default(); |
@@ -129,7 +134,17 @@ impl ProjectWorkspace { | |||
129 | json_project::Edition::Edition2015 => Edition::Edition2015, | 134 | json_project::Edition::Edition2015 => Edition::Edition2015, |
130 | json_project::Edition::Edition2018 => Edition::Edition2018, | 135 | json_project::Edition::Edition2018 => Edition::Edition2018, |
131 | }; | 136 | }; |
132 | crates.insert(crate_id, crate_graph.add_crate_root(file_id, edition)); | 137 | let mut cfg_options = default_cfg_options.clone(); |
138 | for name in &krate.atom_cfgs { | ||
139 | cfg_options = cfg_options.atom(name.into()); | ||
140 | } | ||
141 | for (key, value) in &krate.key_value_cfgs { | ||
142 | cfg_options = cfg_options.key_value(key.into(), value.into()); | ||
143 | } | ||
144 | crates.insert( | ||
145 | crate_id, | ||
146 | crate_graph.add_crate_root(file_id, edition, cfg_options), | ||
147 | ); | ||
133 | } | 148 | } |
134 | } | 149 | } |
135 | 150 | ||
@@ -155,7 +170,10 @@ impl ProjectWorkspace { | |||
155 | let mut sysroot_crates = FxHashMap::default(); | 170 | let mut sysroot_crates = FxHashMap::default(); |
156 | for krate in sysroot.crates() { | 171 | for krate in sysroot.crates() { |
157 | if let Some(file_id) = load(krate.root(&sysroot)) { | 172 | if let Some(file_id) = load(krate.root(&sysroot)) { |
158 | let crate_id = crate_graph.add_crate_root(file_id, Edition::Edition2018); | 173 | // Crates from sysroot have `cfg(test)` disabled |
174 | let cfg_options = default_cfg_options.clone().remove_atom(&"test".into()); | ||
175 | let crate_id = | ||
176 | crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); | ||
159 | sysroot_crates.insert(krate, crate_id); | 177 | sysroot_crates.insert(krate, crate_id); |
160 | names.insert(crate_id, krate.name(&sysroot).to_string()); | 178 | names.insert(crate_id, krate.name(&sysroot).to_string()); |
161 | } | 179 | } |
@@ -184,7 +202,11 @@ impl ProjectWorkspace { | |||
184 | let root = tgt.root(&cargo); | 202 | let root = tgt.root(&cargo); |
185 | if let Some(file_id) = load(root) { | 203 | if let Some(file_id) = load(root) { |
186 | let edition = pkg.edition(&cargo); | 204 | let edition = pkg.edition(&cargo); |
187 | let crate_id = crate_graph.add_crate_root(file_id, edition); | 205 | let cfg_options = default_cfg_options |
206 | .clone() | ||
207 | .features(pkg.features(&cargo).iter().map(Into::into)); | ||
208 | let crate_id = | ||
209 | crate_graph.add_crate_root(file_id, edition, cfg_options); | ||
188 | names.insert(crate_id, pkg.name(&cargo).to_string()); | 210 | names.insert(crate_id, pkg.name(&cargo).to_string()); |
189 | if tgt.kind(&cargo) == TargetKind::Lib { | 211 | if tgt.kind(&cargo) == TargetKind::Lib { |
190 | lib_tgt = Some(crate_id); | 212 | lib_tgt = Some(crate_id); |
@@ -284,3 +306,32 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf> { | |||
284 | } | 306 | } |
285 | Err(format!("can't find Cargo.toml at {}", path.display()))? | 307 | Err(format!("can't find Cargo.toml at {}", path.display()))? |
286 | } | 308 | } |
309 | |||
310 | pub fn get_rustc_cfg_options() -> CfgOptions { | ||
311 | let mut cfg_options = CfgOptions::default(); | ||
312 | |||
313 | match (|| -> Result<_> { | ||
314 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. | ||
315 | let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?; | ||
316 | if !output.status.success() { | ||
317 | Err("failed to get rustc cfgs")?; | ||
318 | } | ||
319 | Ok(String::from_utf8(output.stdout)?) | ||
320 | })() { | ||
321 | Ok(rustc_cfgs) => { | ||
322 | for line in rustc_cfgs.lines() { | ||
323 | match line.find('=') { | ||
324 | None => cfg_options = cfg_options.atom(line.into()), | ||
325 | Some(pos) => { | ||
326 | let key = &line[..pos]; | ||
327 | let value = line[pos + 1..].trim_matches('"'); | ||
328 | cfg_options = cfg_options.key_value(key.into(), value.into()); | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | Err(e) => log::error!("failed to get rustc cfgs: {}", e), | ||
334 | } | ||
335 | |||
336 | cfg_options | ||
337 | } | ||
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 0c27d4f4b..35d6df5cb 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
1 | use std::{ | 3 | use std::{ |
2 | env, | 4 | env, |
3 | path::{Path, PathBuf}, | 5 | path::{Path, PathBuf}, |