From 2980ba1fde50a6fc8863750b9dd7f09e3c1227ce Mon Sep 17 00:00:00 2001 From: robojumper Date: Mon, 4 May 2020 13:29:09 +0200 Subject: [PATCH 1/3] Support build.rs cargo:rustc-cfg --- crates/ra_cfg/src/lib.rs | 9 ++ .../ra_project_model/src/cargo_workspace.rs | 10 +- crates/ra_project_model/src/lib.rs | 7 + .../rust-analyzer/tests/heavy_tests/main.rs | 135 +++++++++++++++++- 4 files changed, 158 insertions(+), 3 deletions(-) diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs index 51d953f6e896..697a0458147d 100644 --- a/crates/ra_cfg/src/lib.rs +++ b/crates/ra_cfg/src/lib.rs @@ -53,4 +53,13 @@ impl CfgOptions { pub fn insert_features(&mut self, iter: impl IntoIterator) { iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat)); } + + /// Shortcut to set cfgs + pub fn insert_cfgs(&mut self, iter: impl IntoIterator) { + iter.into_iter().for_each(|cfg| match cfg.find('=') { + Some(split) => self + .insert_key_value(cfg[0..split].into(), cfg[split + 1..].trim_matches('"').into()), + None => self.insert_atom(cfg), + }); + } } diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 362ee30fe045..afbd301646bc 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -83,6 +83,7 @@ pub struct PackageData { pub dependencies: Vec, pub edition: Edition, pub features: Vec, + pub cfgs: Vec, pub out_dir: Option, pub proc_macro_dylib_path: Option, } @@ -165,10 +166,12 @@ impl CargoWorkspace { })?; let mut out_dir_by_id = FxHashMap::default(); + let mut cfgs = FxHashMap::default(); let mut proc_macro_dylib_paths = FxHashMap::default(); if cargo_features.load_out_dirs_from_check { let resources = load_extern_resources(cargo_toml, cargo_features)?; out_dir_by_id = resources.out_dirs; + cfgs = resources.cfgs; proc_macro_dylib_paths = resources.proc_dylib_paths; } @@ -194,6 +197,7 @@ impl CargoWorkspace { edition, dependencies: Vec::new(), features: Vec::new(), + cfgs: cfgs.get(&id).cloned().unwrap_or_default(), out_dir: out_dir_by_id.get(&id).cloned(), proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(), }); @@ -275,6 +279,7 @@ impl CargoWorkspace { pub struct ExternResources { out_dirs: FxHashMap, proc_dylib_paths: FxHashMap, + cfgs: FxHashMap>, } pub fn load_extern_resources( @@ -300,8 +305,9 @@ pub fn load_extern_resources( for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { if let Ok(message) = message { match message { - Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { - res.out_dirs.insert(package_id, out_dir); + Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { + res.out_dirs.insert(package_id.clone(), out_dir); + res.cfgs.insert(package_id, cfgs); } Message::CompilerArtifact(message) => { diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 731cbd291818..2d5d61b611f3 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -399,6 +399,13 @@ impl ProjectWorkspace { let cfg_options = { let mut opts = default_cfg_options.clone(); opts.insert_features(cargo[pkg].features.iter().map(Into::into)); + opts.insert_cfgs( + cargo[pkg] + .cfgs + .iter() + .filter_map(|c| c.to_str()) + .map(Into::into), + ); opts }; let mut env = Env::default(); diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index a218da76d6c5..e94fbce3a1d5 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs @@ -9,7 +9,8 @@ use lsp_types::{ }; use rust_analyzer::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, - Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams, + Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest, OnEnter, Runnables, + RunnablesParams, }; use serde_json::json; use tempfile::TempDir; @@ -707,3 +708,135 @@ pub fn foo(_input: TokenStream) -> TokenStream { let value = res.get("contents").unwrap().get("value").unwrap().to_string(); assert_eq!(value, r#""```rust\nfoo::Bar\nfn bar()\n```""#) } + +#[test] +fn build_rs_cfgs() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r###" +//- Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- build.rs + +fn main() { + println!("cargo:rustc-cfg=atom_cfg"); + println!("cargo:rustc-cfg=featlike=\"set\""); + println!("cargo:rerun-if-changed=build.rs"); +} +//- src/main.rs +#[cfg(atom_cfg)] +struct A; + +#[cfg(bad_atom_cfg)] +struct A; + +#[cfg(featlike = "set")] +struct B; + +#[cfg(featlike = "not_set")] +struct B; + +fn main() { + let va = A; + let vb = B; +} +"###, + ) + .with_config(|config| { + config.cargo.load_out_dirs_from_check = true; + }) + .server(); + server.wait_until_workspace_is_loaded(); + server.request::( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(13, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { + "character": 10, + "line": 13 + }, + "start": { + "character": 8, + "line":13 + } + }, + "targetRange": { + "end": { + "character": 9, + "line": 1 + }, + "start": { + "character": 0, + "line":0 + } + }, + "targetSelectionRange": { + "end": { + "character": 8, + "line": 1 + }, + "start": { + "character": 7, + "line": 1 + } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); + server.request::( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(14, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { + "character": 10, + "line": 14 + }, + "start": { + "character": 8, + "line":14 + } + }, + "targetRange": { + "end": { + "character": 9, + "line": 7 + }, + "start": { + "character": 0, + "line":6 + } + }, + "targetSelectionRange": { + "end": { + "character": 8, + "line": 7 + }, + "start": { + "character": 7, + "line": 7 + } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); +} From 059fc8696331c2413565e8c682067c76aa6acaf8 Mon Sep 17 00:00:00 2001 From: robojumper Date: Tue, 5 May 2020 14:53:18 +0200 Subject: [PATCH 2/3] Merge heavy tests --- .../rust-analyzer/tests/heavy_tests/main.rs | 239 ++++++++---------- 1 file changed, 105 insertions(+), 134 deletions(-) diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index e94fbce3a1d5..2e52a29a8eec 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs @@ -575,7 +575,7 @@ version = \"0.0.0\" } #[test] -fn resolve_include_concat_env() { +fn out_dirs_check() { if skip_slow_tests() { return; } @@ -598,11 +598,28 @@ fn main() { r#"pub fn message() -> &'static str { "Hello, World!" }"#, ) .unwrap(); + println!("cargo:rustc-cfg=atom_cfg"); + println!("cargo:rustc-cfg=featlike=\"set\""); println!("cargo:rerun-if-changed=build.rs"); } //- src/main.rs include!(concat!(env!("OUT_DIR"), "/hello.rs")); +#[cfg(atom_cfg)] +struct A; +#[cfg(bad_atom_cfg)] +struct A; +#[cfg(featlike = "set")] +struct B; +#[cfg(featlike = "not_set")] +struct B; + +fn main() { + let va = A; + let vb = B; + message(); +} + fn main() { message(); } "###, ) @@ -614,12 +631,98 @@ fn main() { message(); } let res = server.send_request::(GotoDefinitionParams { text_document_position_params: TextDocumentPositionParams::new( server.doc_id("src/main.rs"), - Position::new(2, 15), + Position::new(14, 8), ), work_done_progress_params: Default::default(), partial_result_params: Default::default(), }); assert!(format!("{}", res).contains("hello.rs")); + server.request::( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(12, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { + "character": 10, + "line": 12 + }, + "start": { + "character": 8, + "line": 12 + } + }, + "targetRange": { + "end": { + "character": 9, + "line": 3 + }, + "start": { + "character": 0, + "line": 2 + } + }, + "targetSelectionRange": { + "end": { + "character": 8, + "line": 3 + }, + "start": { + "character": 7, + "line": 3 + } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); + server.request::( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(13, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { + "character": 10, + "line": 13 + }, + "start": { + "character": 8, + "line":13 + } + }, + "targetRange": { + "end": { + "character": 9, + "line": 7 + }, + "start": { + "character": 0, + "line":6 + } + }, + "targetSelectionRange": { + "end": { + "character": 8, + "line": 7 + }, + "start": { + "character": 7, + "line": 7 + } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); } #[test] @@ -708,135 +811,3 @@ pub fn foo(_input: TokenStream) -> TokenStream { let value = res.get("contents").unwrap().get("value").unwrap().to_string(); assert_eq!(value, r#""```rust\nfoo::Bar\nfn bar()\n```""#) } - -#[test] -fn build_rs_cfgs() { - if skip_slow_tests() { - return; - } - - let server = Project::with_fixture( - r###" -//- Cargo.toml -[package] -name = "foo" -version = "0.0.0" - -//- build.rs - -fn main() { - println!("cargo:rustc-cfg=atom_cfg"); - println!("cargo:rustc-cfg=featlike=\"set\""); - println!("cargo:rerun-if-changed=build.rs"); -} -//- src/main.rs -#[cfg(atom_cfg)] -struct A; - -#[cfg(bad_atom_cfg)] -struct A; - -#[cfg(featlike = "set")] -struct B; - -#[cfg(featlike = "not_set")] -struct B; - -fn main() { - let va = A; - let vb = B; -} -"###, - ) - .with_config(|config| { - config.cargo.load_out_dirs_from_check = true; - }) - .server(); - server.wait_until_workspace_is_loaded(); - server.request::( - GotoDefinitionParams { - text_document_position_params: TextDocumentPositionParams::new( - server.doc_id("src/main.rs"), - Position::new(13, 9), - ), - work_done_progress_params: Default::default(), - partial_result_params: Default::default(), - }, - json!([{ - "originSelectionRange": { - "end": { - "character": 10, - "line": 13 - }, - "start": { - "character": 8, - "line":13 - } - }, - "targetRange": { - "end": { - "character": 9, - "line": 1 - }, - "start": { - "character": 0, - "line":0 - } - }, - "targetSelectionRange": { - "end": { - "character": 8, - "line": 1 - }, - "start": { - "character": 7, - "line": 1 - } - }, - "targetUri": "file:///[..]src/main.rs" - }]), - ); - server.request::( - GotoDefinitionParams { - text_document_position_params: TextDocumentPositionParams::new( - server.doc_id("src/main.rs"), - Position::new(14, 9), - ), - work_done_progress_params: Default::default(), - partial_result_params: Default::default(), - }, - json!([{ - "originSelectionRange": { - "end": { - "character": 10, - "line": 14 - }, - "start": { - "character": 8, - "line":14 - } - }, - "targetRange": { - "end": { - "character": 9, - "line": 7 - }, - "start": { - "character": 0, - "line":6 - } - }, - "targetSelectionRange": { - "end": { - "character": 8, - "line": 7 - }, - "start": { - "character": 7, - "line": 7 - } - }, - "targetUri": "file:///[..]src/main.rs" - }]), - ); -} From f2dd233ddc60b647fe9c32ea2d712224005ae99e Mon Sep 17 00:00:00 2001 From: robojumper Date: Tue, 5 May 2020 14:53:52 +0200 Subject: [PATCH 3/3] Assume cargo_metadata uses String for cfgs soon --- crates/ra_project_model/src/cargo_workspace.rs | 11 ++++++++--- crates/ra_project_model/src/lib.rs | 8 +------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index afbd301646bc..bf83adc42a30 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -83,7 +83,7 @@ pub struct PackageData { pub dependencies: Vec, pub edition: Edition, pub features: Vec, - pub cfgs: Vec, + pub cfgs: Vec, pub out_dir: Option, pub proc_macro_dylib_path: Option, } @@ -279,7 +279,7 @@ impl CargoWorkspace { pub struct ExternResources { out_dirs: FxHashMap, proc_dylib_paths: FxHashMap, - cfgs: FxHashMap>, + cfgs: FxHashMap>, } pub fn load_extern_resources( @@ -307,7 +307,12 @@ pub fn load_extern_resources( match message { Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { res.out_dirs.insert(package_id.clone(), out_dir); - res.cfgs.insert(package_id, cfgs); + res.cfgs.insert( + package_id, + // FIXME: Current `cargo_metadata` uses `PathBuf` instead of `String`, + // change when https://github.com/oli-obk/cargo_metadata/pulls/112 reaches crates.io + cfgs.iter().filter_map(|c| c.to_str().map(|s| s.to_owned())).collect(), + ); } Message::CompilerArtifact(message) => { diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 2d5d61b611f3..7231da221a4b 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -399,13 +399,7 @@ impl ProjectWorkspace { let cfg_options = { let mut opts = default_cfg_options.clone(); opts.insert_features(cargo[pkg].features.iter().map(Into::into)); - opts.insert_cfgs( - cargo[pkg] - .cfgs - .iter() - .filter_map(|c| c.to_str()) - .map(Into::into), - ); + opts.insert_cfgs(cargo[pkg].cfgs.iter().map(Into::into)); opts }; let mut env = Env::default();