aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_project_model')
-rw-r--r--crates/ra_project_model/Cargo.toml1
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs6
-rw-r--r--crates/ra_project_model/src/json_project.rs3
-rw-r--r--crates/ra_project_model/src/lib.rs55
4 files changed, 62 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
13ra_arena = { path = "../ra_arena" } 13ra_arena = { path = "../ra_arena" }
14ra_db = { path = "../ra_db" } 14ra_db = { path = "../ra_db" }
15ra_cfg = { path = "../ra_cfg" }
15 16
16serde = { version = "1.0.89", features = ["derive"] } 17serde = { version = "1.0.89", features = ["derive"] }
17serde_json = "1.0.39" 18serde_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 805eaa178..28dadea9d 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -39,6 +39,7 @@ struct PackageData {
39 is_member: bool, 39 is_member: bool,
40 dependencies: Vec<PackageDependency>, 40 dependencies: Vec<PackageDependency>,
41 edition: Edition, 41 edition: Edition,
42 features: Vec<String>,
42} 43}
43 44
44#[derive(Debug, Clone)] 45#[derive(Debug, Clone)]
@@ -91,6 +92,9 @@ impl Package {
91 pub fn edition(self, ws: &CargoWorkspace) -> Edition { 92 pub fn edition(self, ws: &CargoWorkspace) -> Edition {
92 ws.packages[self].edition 93 ws.packages[self].edition
93 } 94 }
95 pub fn features(self, ws: &CargoWorkspace) -> &[String] {
96 &ws.packages[self].features
97 }
94 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 {
95 ws.packages[self].targets.iter().cloned() 99 ws.packages[self].targets.iter().cloned()
96 } 100 }
@@ -144,6 +148,7 @@ impl CargoWorkspace {
144 is_member, 148 is_member,
145 edition: Edition::from_string(&meta_pkg.edition), 149 edition: Edition::from_string(&meta_pkg.edition),
146 dependencies: Vec::new(), 150 dependencies: Vec::new(),
151 features: Vec::new(),
147 }); 152 });
148 let pkg_data = &mut packages[pkg]; 153 let pkg_data = &mut packages[pkg];
149 pkg_by_id.insert(meta_pkg.id.clone(), pkg); 154 pkg_by_id.insert(meta_pkg.id.clone(), pkg);
@@ -164,6 +169,7 @@ impl CargoWorkspace {
164 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] };
165 packages[source].dependencies.push(dep); 170 packages[source].dependencies.push(dep);
166 } 171 }
172 packages[source].features.extend(node.features);
167 } 173 }
168 174
169 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 54ddca2cb..1bacb1d09 100644
--- a/crates/ra_project_model/src/json_project.rs
+++ b/crates/ra_project_model/src/json_project.rs
@@ -2,6 +2,7 @@
2 2
3use std::path::PathBuf; 3use std::path::PathBuf;
4 4
5use rustc_hash::{FxHashMap, FxHashSet};
5use serde::Deserialize; 6use serde::Deserialize;
6 7
7/// 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
@@ -19,6 +20,8 @@ pub struct Crate {
19 pub(crate) root_module: PathBuf, 20 pub(crate) root_module: PathBuf,
20 pub(crate) edition: Edition, 21 pub(crate) edition: Edition,
21 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>,
22} 25}
23 26
24#[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 5d3078598..640a5ebd3 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -9,8 +9,10 @@ use std::{
9 fs::File, 9 fs::File,
10 io::BufReader, 10 io::BufReader,
11 path::{Path, PathBuf}, 11 path::{Path, PathBuf},
12 process::Command,
12}; 13};
13 14
15use ra_cfg::CfgOptions;
14use ra_db::{CrateGraph, CrateId, Edition, FileId}; 16use ra_db::{CrateGraph, CrateId, Edition, FileId};
15use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
16use serde_json::from_reader; 18use serde_json::from_reader;
@@ -117,6 +119,7 @@ impl ProjectWorkspace {
117 119
118 pub fn to_crate_graph( 120 pub fn to_crate_graph(
119 &self, 121 &self,
122 default_cfg_options: &CfgOptions,
120 load: &mut dyn FnMut(&Path) -> Option<FileId>, 123 load: &mut dyn FnMut(&Path) -> Option<FileId>,
121 ) -> (CrateGraph, FxHashMap<CrateId, String>) { 124 ) -> (CrateGraph, FxHashMap<CrateId, String>) {
122 let mut crate_graph = CrateGraph::default(); 125 let mut crate_graph = CrateGraph::default();
@@ -131,7 +134,17 @@ impl ProjectWorkspace {
131 json_project::Edition::Edition2015 => Edition::Edition2015, 134 json_project::Edition::Edition2015 => Edition::Edition2015,
132 json_project::Edition::Edition2018 => Edition::Edition2018, 135 json_project::Edition::Edition2018 => Edition::Edition2018,
133 }; 136 };
134 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 );
135 } 148 }
136 } 149 }
137 150
@@ -157,7 +170,10 @@ impl ProjectWorkspace {
157 let mut sysroot_crates = FxHashMap::default(); 170 let mut sysroot_crates = FxHashMap::default();
158 for krate in sysroot.crates() { 171 for krate in sysroot.crates() {
159 if let Some(file_id) = load(krate.root(&sysroot)) { 172 if let Some(file_id) = load(krate.root(&sysroot)) {
160 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);
161 sysroot_crates.insert(krate, crate_id); 177 sysroot_crates.insert(krate, crate_id);
162 names.insert(crate_id, krate.name(&sysroot).to_string()); 178 names.insert(crate_id, krate.name(&sysroot).to_string());
163 } 179 }
@@ -186,7 +202,11 @@ impl ProjectWorkspace {
186 let root = tgt.root(&cargo); 202 let root = tgt.root(&cargo);
187 if let Some(file_id) = load(root) { 203 if let Some(file_id) = load(root) {
188 let edition = pkg.edition(&cargo); 204 let edition = pkg.edition(&cargo);
189 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);
190 names.insert(crate_id, pkg.name(&cargo).to_string()); 210 names.insert(crate_id, pkg.name(&cargo).to_string());
191 if tgt.kind(&cargo) == TargetKind::Lib { 211 if tgt.kind(&cargo) == TargetKind::Lib {
192 lib_tgt = Some(crate_id); 212 lib_tgt = Some(crate_id);
@@ -286,3 +306,32 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
286 } 306 }
287 Err(format!("can't find Cargo.toml at {}", path.display()))? 307 Err(format!("can't find Cargo.toml at {}", path.display()))?
288} 308}
309
310pub 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}