From 3795f6643a37df3814c538fc475ac1c857fe9eda Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 17:46:33 +0800 Subject: [PATCH 1/7] Add target directory to CargoWorkspace --- crates/ra_project_model/src/cargo_workspace.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 28dadea9d7e0..e978a3143f90 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,7 @@ 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 { From dab23489129b8909c09da74df07d24884a367777 Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 17:55:41 +0800 Subject: [PATCH 2/7] Add env map to CrateGraph --- crates/ra_db/src/input.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 23148096cb1c..e8d70d7d1e7e 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -76,6 +76,7 @@ impl SourceRoot { #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct CrateGraph { arena: FxHashMap, + env: FxHashMap, } #[derive(Debug)] @@ -148,6 +149,11 @@ impl CrateGraph { crate_id } + /// Sets environment variable available trough `env!(VARIABLE_NAME)` macro for crates in crate graph. + pub fn set_env(&mut self, env: &str, value: &str) { + self.env.insert(env.to_owned(), value.to_owned()); + } + pub fn cfg_options(&self, crate_id: CrateId) -> &CfgOptions { &self.arena[&crate_id].cfg_options } From 14f24e87b7119deec078ad177b31e2c7862b6719 Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 17:56:09 +0800 Subject: [PATCH 3/7] Add find_out_dir heuristic template --- crates/ra_project_model/src/lib.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 640a5ebd3213..2abb3967a1f3 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -167,6 +167,12 @@ impl ProjectWorkspace { } } ProjectWorkspace::Cargo { cargo, sysroot } => { + // Find workspace's OUT_DIR inside target/ directory. + // FIXME: should be replaced by path to OUT_DIR coming from metadata, but that would require upstream change to cargo + if let Some(dir) = find_out_dir(&cargo.target_directory) { + crate_graph.set_env("OUT_DIR", dir); + } + let mut sysroot_crates = FxHashMap::default(); for krate in sysroot.crates() { if let Some(file_id) = load(krate.root(&sysroot)) { @@ -273,6 +279,13 @@ impl ProjectWorkspace { .map(|root| root.path.as_ref()), } } + + /// A heuristic that finds 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 { From cb1cc1e5eaa4fc6e7cad101590e5ac3dfa6f3f23 Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 17:56:24 +0800 Subject: [PATCH 4/7] rustfmt --- crates/ra_project_model/src/cargo_workspace.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index e978a3143f90..d02fa1d6b88e 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -173,7 +173,12 @@ impl CargoWorkspace { packages[source].features.extend(node.features); } - Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root, target_directory: meta.target_directory }) + Ok(CargoWorkspace { + packages, + targets, + workspace_root: meta.workspace_root, + target_directory: meta.target_directory, + }) } pub fn packages<'a>(&'a self) -> impl Iterator + ExactSizeIterator + 'a { From fe41609a6401318b3801db1999dbbd5d0624f54e Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 17:58:12 +0800 Subject: [PATCH 5/7] Fix compile error --- crates/ra_project_model/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 2abb3967a1f3..a9ac8ce5ab21 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -169,8 +169,8 @@ impl ProjectWorkspace { ProjectWorkspace::Cargo { cargo, sysroot } => { // Find workspace's OUT_DIR inside target/ directory. // FIXME: should be replaced by path to OUT_DIR coming from metadata, but that would require upstream change to cargo - if let Some(dir) = find_out_dir(&cargo.target_directory) { - crate_graph.set_env("OUT_DIR", dir); + if let Some(dir) = Self::find_out_dir(&cargo.target_directory) { + crate_graph.set_env("OUT_DIR", &dir); } let mut sysroot_crates = FxHashMap::default(); @@ -280,8 +280,8 @@ impl ProjectWorkspace { } } - /// A heuristic that finds the `OUT_DIR` in the specific `target/` directory of `cargo` workspace. - fn find_out_dir(target_path: &PathBuf) -> Option { + /// 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 From 0e33055f3f634fd79c9573fbf1a96de322c7adf3 Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Tue, 8 Oct 2019 18:16:52 +0800 Subject: [PATCH 6/7] Move env map further down from CrateGraph to CrateData --- crates/ra_db/src/input.rs | 40 +++++++++++++++++--------- crates/ra_hir/src/mock.rs | 5 ++-- crates/ra_ide_api/src/lib.rs | 2 +- crates/ra_ide_api/src/mock_analysis.rs | 6 ++-- crates/ra_ide_api/src/parent_module.rs | 3 +- crates/ra_project_model/src/lib.rs | 25 +++++++++------- 6 files changed, 50 insertions(+), 31 deletions(-) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index e8d70d7d1e7e..1ca67a8c280b 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -76,7 +76,6 @@ impl SourceRoot { #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct CrateGraph { arena: FxHashMap, - env: FxHashMap, } #[derive(Debug)] @@ -112,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 trough `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)] @@ -142,18 +153,19 @@ 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 } - /// Sets environment variable available trough `env!(VARIABLE_NAME)` macro for crates in crate graph. - pub fn set_env(&mut self, env: &str, value: &str) { - self.env.insert(env.to_owned(), value.to_owned()); - } - pub fn cfg_options(&self, crate_id: CrateId) -> &CfgOptions { &self.arena[&crate_id].cfg_options } @@ -243,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()); @@ -254,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/lib.rs b/crates/ra_project_model/src/lib.rs index a9ac8ce5ab21..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), ); } } @@ -167,19 +167,18 @@ impl ProjectWorkspace { } } ProjectWorkspace::Cargo { cargo, sysroot } => { - // Find workspace's OUT_DIR inside target/ directory. - // FIXME: should be replaced by path to OUT_DIR coming from metadata, but that would require upstream change to cargo - if let Some(dir) = Self::find_out_dir(&cargo.target_directory) { - crate_graph.set_env("OUT_DIR", &dir); - } - let mut sysroot_crates = FxHashMap::default(); for krate in sysroot.crates() { 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()); } @@ -211,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); From b90693d7de162eb0ba3917c992c91808de7bbb53 Mon Sep 17 00:00:00 2001 From: Evgenii Ponomarev Date: Wed, 9 Oct 2019 13:47:47 +0800 Subject: [PATCH 7/7] Fix typo --- crates/ra_db/src/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 1ca67a8c280b..14f5f104a3c3 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -129,7 +129,7 @@ impl CrateData { self.dependencies.push(Dependency { name, crate_id }) } - /// Sets environment variable available trough `env!(VARIABLE_NAME)` macro for crates in crate graph. + /// 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); }