aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs48
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs42
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs28
-rw-r--r--crates/rust-analyzer/src/req.rs1
-rw-r--r--crates/rust-analyzer/src/world.rs1
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs15
8 files changed, 98 insertions, 42 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index d0459d9b0..db9838cb5 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -102,6 +102,7 @@ struct MacroDirective {
102 module_id: LocalModuleId, 102 module_id: LocalModuleId,
103 ast_id: AstIdWithPath<ast::MacroCall>, 103 ast_id: AstIdWithPath<ast::MacroCall>,
104 legacy: Option<MacroCallId>, 104 legacy: Option<MacroCallId>,
105 depth: usize,
105} 106}
106 107
107#[derive(Clone, Debug, Eq, PartialEq)] 108#[derive(Clone, Debug, Eq, PartialEq)]
@@ -134,6 +135,7 @@ where
134 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 135 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
135 ModCollector { 136 ModCollector {
136 def_collector: &mut *self, 137 def_collector: &mut *self,
138 macro_depth: 0,
137 module_id, 139 module_id,
138 file_id: file_id.into(), 140 file_id: file_id.into(),
139 raw_items: &raw_items, 141 raw_items: &raw_items,
@@ -516,7 +518,7 @@ where
516 macros.retain(|directive| { 518 macros.retain(|directive| {
517 if let Some(call_id) = directive.legacy { 519 if let Some(call_id) = directive.legacy {
518 res = ReachedFixedPoint::No; 520 res = ReachedFixedPoint::No;
519 resolved.push((directive.module_id, call_id)); 521 resolved.push((directive.module_id, call_id, directive.depth));
520 return false; 522 return false;
521 } 523 }
522 524
@@ -530,7 +532,7 @@ where
530 ); 532 );
531 resolved_res.resolved_def.take_macros() 533 resolved_res.resolved_def.take_macros()
532 }) { 534 }) {
533 resolved.push((directive.module_id, call_id)); 535 resolved.push((directive.module_id, call_id, directive.depth));
534 res = ReachedFixedPoint::No; 536 res = ReachedFixedPoint::No;
535 return false; 537 return false;
536 } 538 }
@@ -541,7 +543,7 @@ where
541 if let Some(call_id) = 543 if let Some(call_id) =
542 directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path)) 544 directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path))
543 { 545 {
544 resolved.push((directive.module_id, call_id)); 546 resolved.push((directive.module_id, call_id, 0));
545 res = ReachedFixedPoint::No; 547 res = ReachedFixedPoint::No;
546 return false; 548 return false;
547 } 549 }
@@ -552,8 +554,12 @@ where
552 self.unexpanded_macros = macros; 554 self.unexpanded_macros = macros;
553 self.unexpanded_attribute_macros = attribute_macros; 555 self.unexpanded_attribute_macros = attribute_macros;
554 556
555 for (module_id, macro_call_id) in resolved { 557 for (module_id, macro_call_id, depth) in resolved {
556 self.collect_macro_expansion(module_id, macro_call_id); 558 if depth > 1024 {
559 log::debug!("Max macro expansion depth reached");
560 continue;
561 }
562 self.collect_macro_expansion(module_id, macro_call_id, depth);
557 } 563 }
558 564
559 res 565 res
@@ -573,12 +579,18 @@ where
573 None 579 None
574 } 580 }
575 581
576 fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) { 582 fn collect_macro_expansion(
583 &mut self,
584 module_id: LocalModuleId,
585 macro_call_id: MacroCallId,
586 depth: usize,
587 ) {
577 let file_id: HirFileId = macro_call_id.as_file(); 588 let file_id: HirFileId = macro_call_id.as_file();
578 let raw_items = self.db.raw_items(file_id); 589 let raw_items = self.db.raw_items(file_id);
579 let mod_dir = self.mod_dirs[&module_id].clone(); 590 let mod_dir = self.mod_dirs[&module_id].clone();
580 ModCollector { 591 ModCollector {
581 def_collector: &mut *self, 592 def_collector: &mut *self,
593 macro_depth: depth,
582 file_id, 594 file_id,
583 module_id, 595 module_id,
584 raw_items: &raw_items, 596 raw_items: &raw_items,
@@ -595,6 +607,7 @@ where
595/// Walks a single module, populating defs, imports and macros 607/// Walks a single module, populating defs, imports and macros
596struct ModCollector<'a, D> { 608struct ModCollector<'a, D> {
597 def_collector: D, 609 def_collector: D,
610 macro_depth: usize,
598 module_id: LocalModuleId, 611 module_id: LocalModuleId,
599 file_id: HirFileId, 612 file_id: HirFileId,
600 raw_items: &'a raw::RawItems, 613 raw_items: &'a raw::RawItems,
@@ -684,6 +697,7 @@ where
684 697
685 ModCollector { 698 ModCollector {
686 def_collector: &mut *self.def_collector, 699 def_collector: &mut *self.def_collector,
700 macro_depth: self.macro_depth,
687 module_id, 701 module_id,
688 file_id: self.file_id, 702 file_id: self.file_id,
689 raw_items: self.raw_items, 703 raw_items: self.raw_items,
@@ -713,6 +727,7 @@ where
713 let raw_items = self.def_collector.db.raw_items(file_id.into()); 727 let raw_items = self.def_collector.db.raw_items(file_id.into());
714 ModCollector { 728 ModCollector {
715 def_collector: &mut *self.def_collector, 729 def_collector: &mut *self.def_collector,
730 macro_depth: self.macro_depth,
716 module_id, 731 module_id,
717 file_id: file_id.into(), 732 file_id: file_id.into(),
718 raw_items: &raw_items, 733 raw_items: &raw_items,
@@ -887,6 +902,7 @@ where
887 module_id: self.module_id, 902 module_id: self.module_id,
888 ast_id, 903 ast_id,
889 legacy: Some(macro_call_id), 904 legacy: Some(macro_call_id),
905 depth: self.macro_depth + 1,
890 }); 906 });
891 907
892 return; 908 return;
@@ -902,6 +918,7 @@ where
902 module_id: self.module_id, 918 module_id: self.module_id,
903 ast_id, 919 ast_id,
904 legacy: None, 920 legacy: None,
921 depth: self.macro_depth + 1,
905 }); 922 });
906 } 923 }
907 924
@@ -971,13 +988,26 @@ mod tests {
971 } 988 }
972 989
973 #[test] 990 #[test]
974 fn test_macro_expand_will_stop() { 991 fn test_macro_expand_will_stop_1() {
992 do_resolve(
993 r#"
994 macro_rules! foo {
995 ($($ty:ty)*) => { foo!($($ty)*); }
996 }
997 foo!(KABOOM);
998 "#,
999 );
1000 }
1001
1002 #[ignore] // this test does succeed, but takes quite a while :/
1003 #[test]
1004 fn test_macro_expand_will_stop_2() {
975 do_resolve( 1005 do_resolve(
976 r#" 1006 r#"
977 macro_rules! foo { 1007 macro_rules! foo {
978 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); } 1008 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
979 } 1009 }
980foo!(KABOOM); 1010 foo!(KABOOM);
981 "#, 1011 "#,
982 ); 1012 );
983 } 1013 }
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 53751aafb..321861b16 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -19,50 +19,48 @@ impl CargoTargetSpec {
19 pub(crate) fn runnable_args( 19 pub(crate) fn runnable_args(
20 spec: Option<CargoTargetSpec>, 20 spec: Option<CargoTargetSpec>,
21 kind: &RunnableKind, 21 kind: &RunnableKind,
22 ) -> Result<Vec<String>> { 22 ) -> Result<(Vec<String>, Vec<String>)> {
23 let mut res = Vec::new(); 23 let mut args = Vec::new();
24 let mut extra_args = Vec::new();
24 match kind { 25 match kind {
25 RunnableKind::Test { test_id } => { 26 RunnableKind::Test { test_id } => {
26 res.push("test".to_string()); 27 args.push("test".to_string());
27 if let Some(spec) = spec { 28 if let Some(spec) = spec {
28 spec.push_to(&mut res); 29 spec.push_to(&mut args);
29 } 30 }
30 res.push("--".to_string()); 31 extra_args.push(test_id.to_string());
31 res.push(test_id.to_string());
32 if let TestId::Path(_) = test_id { 32 if let TestId::Path(_) = test_id {
33 res.push("--exact".to_string()); 33 extra_args.push("--exact".to_string());
34 } 34 }
35 res.push("--nocapture".to_string()); 35 extra_args.push("--nocapture".to_string());
36 } 36 }
37 RunnableKind::TestMod { path } => { 37 RunnableKind::TestMod { path } => {
38 res.push("test".to_string()); 38 args.push("test".to_string());
39 if let Some(spec) = spec { 39 if let Some(spec) = spec {
40 spec.push_to(&mut res); 40 spec.push_to(&mut args);
41 } 41 }
42 res.push("--".to_string()); 42 extra_args.push(path.to_string());
43 res.push(path.to_string()); 43 extra_args.push("--nocapture".to_string());
44 res.push("--nocapture".to_string());
45 } 44 }
46 RunnableKind::Bench { test_id } => { 45 RunnableKind::Bench { test_id } => {
47 res.push("bench".to_string()); 46 args.push("bench".to_string());
48 if let Some(spec) = spec { 47 if let Some(spec) = spec {
49 spec.push_to(&mut res); 48 spec.push_to(&mut args);
50 } 49 }
51 res.push("--".to_string()); 50 extra_args.push(test_id.to_string());
52 res.push(test_id.to_string());
53 if let TestId::Path(_) = test_id { 51 if let TestId::Path(_) = test_id {
54 res.push("--exact".to_string()); 52 extra_args.push("--exact".to_string());
55 } 53 }
56 res.push("--nocapture".to_string()); 54 extra_args.push("--nocapture".to_string());
57 } 55 }
58 RunnableKind::Bin => { 56 RunnableKind::Bin => {
59 res.push("run".to_string()); 57 args.push("run".to_string());
60 if let Some(spec) = spec { 58 if let Some(spec) = spec {
61 spec.push_to(&mut res); 59 spec.push_to(&mut args);
62 } 60 }
63 } 61 }
64 } 62 }
65 Ok(res) 63 Ok((args, extra_args))
66 } 64 }
67 65
68 pub(crate) fn for_file( 66 pub(crate) fn for_file(
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 084e17b04..6b9a11a87 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -55,6 +55,9 @@ pub struct ServerConfig {
55 55
56 /// Cargo feature configurations. 56 /// Cargo feature configurations.
57 pub cargo_features: CargoFeatures, 57 pub cargo_features: CargoFeatures,
58
59 /// Enabled if the vscode_lldb extension is available.
60 pub vscode_lldb: bool,
58} 61}
59 62
60impl Default for ServerConfig { 63impl Default for ServerConfig {
@@ -76,6 +79,7 @@ impl Default for ServerConfig {
76 additional_out_dirs: FxHashMap::default(), 79 additional_out_dirs: FxHashMap::default(),
77 cargo_features: Default::default(), 80 cargo_features: Default::default(),
78 rustfmt_args: Vec::new(), 81 rustfmt_args: Vec::new(),
82 vscode_lldb: false,
79 } 83 }
80 } 84 }
81} 85}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 2b3b16d35..eb29e8322 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -189,6 +189,7 @@ pub fn main_loop(
189 all_targets: config.cargo_watch_all_targets, 189 all_targets: config.cargo_watch_all_targets,
190 }, 190 },
191 rustfmt_args: config.rustfmt_args, 191 rustfmt_args: config.rustfmt_args,
192 vscode_lldb: config.vscode_lldb,
192 } 193 }
193 }; 194 };
194 195
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 6482f3b77..df3622d61 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -381,6 +381,7 @@ pub fn handle_runnables(
381 label, 381 label,
382 bin: "cargo".to_string(), 382 bin: "cargo".to_string(),
383 args: check_args, 383 args: check_args,
384 extra_args: Vec::new(),
384 env: FxHashMap::default(), 385 env: FxHashMap::default(),
385 cwd: workspace_root.map(|root| root.to_string_lossy().to_string()), 386 cwd: workspace_root.map(|root| root.to_string_lossy().to_string()),
386 }); 387 });
@@ -794,18 +795,35 @@ pub fn handle_code_lens(
794 RunnableKind::Bin => "Run", 795 RunnableKind::Bin => "Run",
795 } 796 }
796 .to_string(); 797 .to_string();
797 let r = to_lsp_runnable(&world, file_id, runnable)?; 798 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
798 let lens = CodeLens { 799 let lens = CodeLens {
799 range: r.range, 800 range: r.range,
800 command: Some(Command { 801 command: Some(Command {
801 title, 802 title,
802 command: "rust-analyzer.runSingle".into(), 803 command: "rust-analyzer.runSingle".into(),
803 arguments: Some(vec![to_value(r).unwrap()]), 804 arguments: Some(vec![to_value(&r).unwrap()]),
804 }), 805 }),
805 data: None, 806 data: None,
806 }; 807 };
807
808 lenses.push(lens); 808 lenses.push(lens);
809
810 if world.options.vscode_lldb {
811 if r.args[0] == "run" {
812 r.args[0] = "build".into();
813 } else {
814 r.args.push("--no-run".into());
815 }
816 let debug_lens = CodeLens {
817 range: r.range,
818 command: Some(Command {
819 title: "Debug".into(),
820 command: "rust-analyzer.debugSingle".into(),
821 arguments: Some(vec![to_value(r).unwrap()]),
822 }),
823 data: None,
824 };
825 lenses.push(debug_lens);
826 }
809 } 827 }
810 828
811 // Handle impls 829 // Handle impls
@@ -952,7 +970,7 @@ fn to_lsp_runnable(
952 runnable: Runnable, 970 runnable: Runnable,
953) -> Result<req::Runnable> { 971) -> Result<req::Runnable> {
954 let spec = CargoTargetSpec::for_file(world, file_id)?; 972 let spec = CargoTargetSpec::for_file(world, file_id)?;
955 let args = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; 973 let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?;
956 let line_index = world.analysis().file_line_index(file_id)?; 974 let line_index = world.analysis().file_line_index(file_id)?;
957 let label = match &runnable.kind { 975 let label = match &runnable.kind {
958 RunnableKind::Test { test_id } => format!("test {}", test_id), 976 RunnableKind::Test { test_id } => format!("test {}", test_id),
@@ -965,6 +983,7 @@ fn to_lsp_runnable(
965 label, 983 label,
966 bin: "cargo".to_string(), 984 bin: "cargo".to_string(),
967 args, 985 args,
986 extra_args,
968 env: { 987 env: {
969 let mut m = FxHashMap::default(); 988 let mut m = FxHashMap::default();
970 m.insert("RUST_BACKTRACE".to_string(), "short".to_string()); 989 m.insert("RUST_BACKTRACE".to_string(), "short".to_string());
@@ -973,6 +992,7 @@ fn to_lsp_runnable(
973 cwd: world.workspace_root_for(file_id).map(|root| root.to_string_lossy().to_string()), 992 cwd: world.workspace_root_for(file_id).map(|root| root.to_string_lossy().to_string()),
974 }) 993 })
975} 994}
995
976fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> { 996fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> {
977 let line_index = world.analysis().file_line_index(file_id)?; 997 let line_index = world.analysis().file_line_index(file_id)?;
978 let res = world 998 let res = world
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs
index a3efe3b9f..156328df8 100644
--- a/crates/rust-analyzer/src/req.rs
+++ b/crates/rust-analyzer/src/req.rs
@@ -169,6 +169,7 @@ pub struct Runnable {
169 pub label: String, 169 pub label: String,
170 pub bin: String, 170 pub bin: String,
171 pub args: Vec<String>, 171 pub args: Vec<String>,
172 pub extra_args: Vec<String>,
172 pub env: FxHashMap<String, String>, 173 pub env: FxHashMap<String, String>,
173 pub cwd: Option<String>, 174 pub cwd: Option<String>,
174} 175}
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 058ce2af8..5743471bf 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -38,6 +38,7 @@ pub struct Options {
38 pub inlay_hints: InlayHintsOptions, 38 pub inlay_hints: InlayHintsOptions,
39 pub rustfmt_args: Vec<String>, 39 pub rustfmt_args: Vec<String>,
40 pub cargo_watch: CheckOptions, 40 pub cargo_watch: CheckOptions,
41 pub vscode_lldb: bool,
41} 42}
42 43
43/// `WorldState` is the primary mutable state of the language server 44/// `WorldState` is the primary mutable state of the language server
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index 970185dec..145429571 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -75,7 +75,8 @@ fn foo() {
75 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None }, 75 RunnablesParams { text_document: server.doc_id("lib.rs"), position: None },
76 json!([ 76 json!([
77 { 77 {
78 "args": [ "test", "--", "foo", "--nocapture" ], 78 "args": [ "test" ],
79 "extraArgs": [ "foo", "--nocapture" ],
79 "bin": "cargo", 80 "bin": "cargo",
80 "env": { "RUST_BACKTRACE": "short" }, 81 "env": { "RUST_BACKTRACE": "short" },
81 "cwd": null, 82 "cwd": null,
@@ -90,6 +91,7 @@ fn foo() {
90 "check", 91 "check",
91 "--all" 92 "--all"
92 ], 93 ],
94 "extraArgs": [],
93 "bin": "cargo", 95 "bin": "cargo",
94 "env": {}, 96 "env": {},
95 "cwd": null, 97 "cwd": null,
@@ -141,13 +143,11 @@ fn main() {}
141 143
142 server.wait_until_workspace_is_loaded(); 144 server.wait_until_workspace_is_loaded();
143 server.request::<Runnables>( 145 server.request::<Runnables>(
144 RunnablesParams { 146 RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None },
145 text_document: server.doc_id("foo/tests/spam.rs"),
146 position: None,
147 },
148 json!([ 147 json!([
149 { 148 {
150 "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--exact", "--nocapture" ], 149 "args": [ "test", "--package", "foo", "--test", "spam" ],
150 "extraArgs": [ "test_eggs", "--exact", "--nocapture" ],
151 "bin": "cargo", 151 "bin": "cargo",
152 "env": { "RUST_BACKTRACE": "short" }, 152 "env": { "RUST_BACKTRACE": "short" },
153 "label": "test test_eggs", 153 "label": "test test_eggs",
@@ -165,6 +165,7 @@ fn main() {}
165 "--test", 165 "--test",
166 "spam" 166 "spam"
167 ], 167 ],
168 "extraArgs": [],
168 "bin": "cargo", 169 "bin": "cargo",
169 "env": {}, 170 "env": {},
170 "cwd": server.path().join("foo"), 171 "cwd": server.path().join("foo"),
@@ -180,7 +181,7 @@ fn main() {}
180 } 181 }
181 } 182 }
182 } 183 }
183 ]) 184 ]),
184 ); 185 );
185} 186}
186 187