aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobojumper <[email protected]>2020-05-04 12:29:09 +0100
committerrobojumper <[email protected]>2020-05-04 12:29:09 +0100
commit2980ba1fde50a6fc8863750b9dd7f09e3c1227ce (patch)
tree6b90bc58f5f7dc661d71d3a4a499ae028a9f43ed
parent6a48a94d47bfd6a340cbdb3f68b5bce4167c8168 (diff)
Support build.rs cargo:rustc-cfg
-rw-r--r--crates/ra_cfg/src/lib.rs9
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs10
-rw-r--r--crates/ra_project_model/src/lib.rs7
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs135
4 files changed, 158 insertions, 3 deletions
diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs
index 51d953f6e..697a04581 100644
--- a/crates/ra_cfg/src/lib.rs
+++ b/crates/ra_cfg/src/lib.rs
@@ -53,4 +53,13 @@ impl CfgOptions {
53 pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) { 53 pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
54 iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat)); 54 iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat));
55 } 55 }
56
57 /// Shortcut to set cfgs
58 pub fn insert_cfgs(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
59 iter.into_iter().for_each(|cfg| match cfg.find('=') {
60 Some(split) => self
61 .insert_key_value(cfg[0..split].into(), cfg[split + 1..].trim_matches('"').into()),
62 None => self.insert_atom(cfg),
63 });
64 }
56} 65}
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 362ee30fe..afbd30164 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 {
83 pub dependencies: Vec<PackageDependency>, 83 pub dependencies: Vec<PackageDependency>,
84 pub edition: Edition, 84 pub edition: Edition,
85 pub features: Vec<String>, 85 pub features: Vec<String>,
86 pub cfgs: Vec<PathBuf>,
86 pub out_dir: Option<PathBuf>, 87 pub out_dir: Option<PathBuf>,
87 pub proc_macro_dylib_path: Option<PathBuf>, 88 pub proc_macro_dylib_path: Option<PathBuf>,
88} 89}
@@ -165,10 +166,12 @@ impl CargoWorkspace {
165 })?; 166 })?;
166 167
167 let mut out_dir_by_id = FxHashMap::default(); 168 let mut out_dir_by_id = FxHashMap::default();
169 let mut cfgs = FxHashMap::default();
168 let mut proc_macro_dylib_paths = FxHashMap::default(); 170 let mut proc_macro_dylib_paths = FxHashMap::default();
169 if cargo_features.load_out_dirs_from_check { 171 if cargo_features.load_out_dirs_from_check {
170 let resources = load_extern_resources(cargo_toml, cargo_features)?; 172 let resources = load_extern_resources(cargo_toml, cargo_features)?;
171 out_dir_by_id = resources.out_dirs; 173 out_dir_by_id = resources.out_dirs;
174 cfgs = resources.cfgs;
172 proc_macro_dylib_paths = resources.proc_dylib_paths; 175 proc_macro_dylib_paths = resources.proc_dylib_paths;
173 } 176 }
174 177
@@ -194,6 +197,7 @@ impl CargoWorkspace {
194 edition, 197 edition,
195 dependencies: Vec::new(), 198 dependencies: Vec::new(),
196 features: Vec::new(), 199 features: Vec::new(),
200 cfgs: cfgs.get(&id).cloned().unwrap_or_default(),
197 out_dir: out_dir_by_id.get(&id).cloned(), 201 out_dir: out_dir_by_id.get(&id).cloned(),
198 proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(), 202 proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
199 }); 203 });
@@ -275,6 +279,7 @@ impl CargoWorkspace {
275pub struct ExternResources { 279pub struct ExternResources {
276 out_dirs: FxHashMap<PackageId, PathBuf>, 280 out_dirs: FxHashMap<PackageId, PathBuf>,
277 proc_dylib_paths: FxHashMap<PackageId, PathBuf>, 281 proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
282 cfgs: FxHashMap<PackageId, Vec<PathBuf>>,
278} 283}
279 284
280pub fn load_extern_resources( 285pub fn load_extern_resources(
@@ -300,8 +305,9 @@ pub fn load_extern_resources(
300 for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { 305 for message in cargo_metadata::parse_messages(output.stdout.as_slice()) {
301 if let Ok(message) = message { 306 if let Ok(message) = message {
302 match message { 307 match message {
303 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { 308 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
304 res.out_dirs.insert(package_id, out_dir); 309 res.out_dirs.insert(package_id.clone(), out_dir);
310 res.cfgs.insert(package_id, cfgs);
305 } 311 }
306 312
307 Message::CompilerArtifact(message) => { 313 Message::CompilerArtifact(message) => {
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 731cbd291..2d5d61b61 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -399,6 +399,13 @@ impl ProjectWorkspace {
399 let cfg_options = { 399 let cfg_options = {
400 let mut opts = default_cfg_options.clone(); 400 let mut opts = default_cfg_options.clone();
401 opts.insert_features(cargo[pkg].features.iter().map(Into::into)); 401 opts.insert_features(cargo[pkg].features.iter().map(Into::into));
402 opts.insert_cfgs(
403 cargo[pkg]
404 .cfgs
405 .iter()
406 .filter_map(|c| c.to_str())
407 .map(Into::into),
408 );
402 opts 409 opts
403 }; 410 };
404 let mut env = Env::default(); 411 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 a218da76d..e94fbce3a 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::{
9}; 9};
10use rust_analyzer::req::{ 10use rust_analyzer::req::{
11 CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, 11 CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument,
12 Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams, 12 Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest, OnEnter, Runnables,
13 RunnablesParams,
13}; 14};
14use serde_json::json; 15use serde_json::json;
15use tempfile::TempDir; 16use tempfile::TempDir;
@@ -707,3 +708,135 @@ pub fn foo(_input: TokenStream) -> TokenStream {
707 let value = res.get("contents").unwrap().get("value").unwrap().to_string(); 708 let value = res.get("contents").unwrap().get("value").unwrap().to_string();
708 assert_eq!(value, r#""```rust\nfoo::Bar\nfn bar()\n```""#) 709 assert_eq!(value, r#""```rust\nfoo::Bar\nfn bar()\n```""#)
709} 710}
711
712#[test]
713fn build_rs_cfgs() {
714 if skip_slow_tests() {
715 return;
716 }
717
718 let server = Project::with_fixture(
719 r###"
720//- Cargo.toml
721[package]
722name = "foo"
723version = "0.0.0"
724
725//- build.rs
726
727fn main() {
728 println!("cargo:rustc-cfg=atom_cfg");
729 println!("cargo:rustc-cfg=featlike=\"set\"");
730 println!("cargo:rerun-if-changed=build.rs");
731}
732//- src/main.rs
733#[cfg(atom_cfg)]
734struct A;
735
736#[cfg(bad_atom_cfg)]
737struct A;
738
739#[cfg(featlike = "set")]
740struct B;
741
742#[cfg(featlike = "not_set")]
743struct B;
744
745fn main() {
746 let va = A;
747 let vb = B;
748}
749"###,
750 )
751 .with_config(|config| {
752 config.cargo.load_out_dirs_from_check = true;
753 })
754 .server();
755 server.wait_until_workspace_is_loaded();
756 server.request::<GotoTypeDefinition>(
757 GotoDefinitionParams {
758 text_document_position_params: TextDocumentPositionParams::new(
759 server.doc_id("src/main.rs"),
760 Position::new(13, 9),
761 ),
762 work_done_progress_params: Default::default(),
763 partial_result_params: Default::default(),
764 },
765 json!([{
766 "originSelectionRange": {
767 "end": {
768 "character": 10,
769 "line": 13
770 },
771 "start": {
772 "character": 8,
773 "line":13
774 }
775 },
776 "targetRange": {
777 "end": {
778 "character": 9,
779 "line": 1
780 },
781 "start": {
782 "character": 0,
783 "line":0
784 }
785 },
786 "targetSelectionRange": {
787 "end": {
788 "character": 8,
789 "line": 1
790 },
791 "start": {
792 "character": 7,
793 "line": 1
794 }
795 },
796 "targetUri": "file:///[..]src/main.rs"
797 }]),
798 );
799 server.request::<GotoTypeDefinition>(
800 GotoDefinitionParams {
801 text_document_position_params: TextDocumentPositionParams::new(
802 server.doc_id("src/main.rs"),
803 Position::new(14, 9),
804 ),
805 work_done_progress_params: Default::default(),
806 partial_result_params: Default::default(),
807 },
808 json!([{
809 "originSelectionRange": {
810 "end": {
811 "character": 10,
812 "line": 14
813 },
814 "start": {
815 "character": 8,
816 "line":14
817 }
818 },
819 "targetRange": {
820 "end": {
821 "character": 9,
822 "line": 7
823 },
824 "start": {
825 "character": 0,
826 "line":6
827 }
828 },
829 "targetSelectionRange": {
830 "end": {
831 "character": 8,
832 "line": 7
833 },
834 "start": {
835 "character": 7,
836 "line": 7
837 }
838 },
839 "targetUri": "file:///[..]src/main.rs"
840 }]),
841 );
842}