diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 23148096cb1c..14f5f104a3c3 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -111,16 +111,28 @@ struct CrateData { edition: Edition, dependencies: Vec, cfg_options: CfgOptions, + env: FxHashMap, } impl CrateData { fn new(file_id: FileId, edition: Edition, cfg_options: CfgOptions) -> CrateData { - CrateData { file_id, edition, dependencies: Vec::new(), cfg_options } + CrateData { + file_id, + edition, + dependencies: Vec::new(), + cfg_options, + env: Default::default(), + } } fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { self.dependencies.push(Dependency { name, crate_id }) } + + /// Sets environment variable available through `env!(VARIABLE_NAME)` macro for crates in crate graph. + pub fn set_env(&mut self, env: &str, value: String) { + self.env.insert(env.to_owned(), value); + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -141,9 +153,15 @@ impl CrateGraph { file_id: FileId, edition: Edition, cfg_options: CfgOptions, + out_dir: Option, ) -> CrateId { let crate_id = CrateId(self.arena.len() as u32); - let prev = self.arena.insert(crate_id, CrateData::new(file_id, edition, cfg_options)); + let mut crate_data = CrateData::new(file_id, edition, cfg_options); + if let Some(out_dir) = out_dir { + crate_data.set_env("OUT_DIR", out_dir.to_owned()); + } + + let prev = self.arena.insert(crate_id, crate_data); assert!(prev.is_none()); crate_id } @@ -237,9 +255,9 @@ mod tests { #[test] fn it_should_panic_because_of_cycle_dependencies() { let mut graph = CrateGraph::default(); - let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default()); - let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default()); - let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default()); + let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default(), None); + let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default(), None); + let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default(), None); assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err()); @@ -248,9 +266,9 @@ mod tests { #[test] fn it_works() { let mut graph = CrateGraph::default(); - let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default()); - let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default()); - let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default()); + let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default(), None); + let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default(), None); + let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default(), None); assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); } diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index f750986b8b32..a7cd44b1e451 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -77,7 +77,8 @@ impl MockDatabase { let mut crate_graph = CrateGraph::default(); for (crate_name, (crate_root, edition, cfg_options, _)) in graph.0.iter() { let crate_root = self.file_id_of(&crate_root); - let crate_id = crate_graph.add_crate_root(crate_root, *edition, cfg_options.clone()); + let crate_id = + crate_graph.add_crate_root(crate_root, *edition, cfg_options.clone(), None); Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone()); ids.insert(crate_name, crate_id); } @@ -185,7 +186,7 @@ impl MockDatabase { if is_crate_root { let mut crate_graph = CrateGraph::default(); - crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default()); + crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default(), None); self.set_crate_graph(Arc::new(crate_graph)); } file_id diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 24f1b91f68c9..d82ef2f356d0 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -326,7 +326,7 @@ impl Analysis { // FIXME: cfg options // Default to enable test for single file. let cfg_options = CfgOptions::default().atom("test".into()); - crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); + crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options, None); change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); change.set_crate_graph(crate_graph); host.apply_change(change); diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 80b71894cdf6..cf2bfc31d33b 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs @@ -96,9 +96,11 @@ impl MockAnalysis { let file_id = FileId(i as u32 + 1); let cfg_options = CfgOptions::default(); if path == "/lib.rs" || path == "/main.rs" { - root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options)); + root_crate = + Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options, None)); } else if path.ends_with("/lib.rs") { - let other_crate = crate_graph.add_crate_root(file_id, Edition2018, cfg_options); + let other_crate = + crate_graph.add_crate_root(file_id, Edition2018, cfg_options, None); let crate_name = path.parent().unwrap().file_name().unwrap(); if let Some(root_crate) = root_crate { crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index 56650984995b..3e19573641b4 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs @@ -89,7 +89,8 @@ mod tests { assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); let mut crate_graph = CrateGraph::default(); - let crate_id = crate_graph.add_crate_root(root_file, Edition2018, CfgOptions::default()); + let crate_id = + crate_graph.add_crate_root(root_file, Edition2018, CfgOptions::default(), None); let mut change = AnalysisChange::new(); change.set_crate_graph(crate_graph); host.apply_change(change); diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 28dadea9d7e0..d02fa1d6b88e 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -21,6 +21,7 @@ pub struct CargoWorkspace { packages: Arena, targets: Arena, pub(crate) workspace_root: PathBuf, + pub(crate) target_directory: PathBuf, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -172,7 +173,12 @@ impl CargoWorkspace { packages[source].features.extend(node.features); } - Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root }) + Ok(CargoWorkspace { + packages, + targets, + workspace_root: meta.workspace_root, + target_directory: meta.target_directory, + }) } pub fn packages<'a>(&'a self) -> impl Iterator + ExactSizeIterator + 'a { diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 640a5ebd3213..630e86351283 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -143,7 +143,7 @@ impl ProjectWorkspace { } crates.insert( crate_id, - crate_graph.add_crate_root(file_id, edition, cfg_options), + crate_graph.add_crate_root(file_id, edition, cfg_options, None), ); } } @@ -172,8 +172,13 @@ impl ProjectWorkspace { if let Some(file_id) = load(krate.root(&sysroot)) { // Crates from sysroot have `cfg(test)` disabled let cfg_options = default_cfg_options.clone().remove_atom(&"test".into()); - let crate_id = - crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); + let crate_id = crate_graph.add_crate_root( + file_id, + Edition::Edition2018, + cfg_options, + Self::find_out_dir(&cargo.target_directory), + ); + sysroot_crates.insert(krate, crate_id); names.insert(crate_id, krate.name(&sysroot).to_string()); } @@ -205,8 +210,12 @@ impl ProjectWorkspace { let cfg_options = default_cfg_options .clone() .features(pkg.features(&cargo).iter().map(Into::into)); - let crate_id = - crate_graph.add_crate_root(file_id, edition, cfg_options); + let crate_id = crate_graph.add_crate_root( + file_id, + edition, + cfg_options, + Self::find_out_dir(&cargo.target_directory), + ); names.insert(crate_id, pkg.name(&cargo).to_string()); if tgt.kind(&cargo) == TargetKind::Lib { lib_tgt = Some(crate_id); @@ -273,6 +282,13 @@ impl ProjectWorkspace { .map(|root| root.path.as_ref()), } } + + /// A heuristic that looks for the `OUT_DIR` in the specific `target/` directory of `cargo` workspace. + fn find_out_dir(_target_path: &PathBuf) -> Option { + // FIXME: put heuristic here + // Should probably traverse the `target//...` path and find a match + None + } } fn find_rust_project_json(path: &Path) -> Option {