aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs65
1 files changed, 25 insertions, 40 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 82738cce3..4590a5184 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -42,25 +42,21 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
42 unresolved_imports: Vec::new(), 42 unresolved_imports: Vec::new(),
43 unexpanded_macros: Vec::new(), 43 unexpanded_macros: Vec::new(),
44 global_macro_scope: FxHashMap::default(), 44 global_macro_scope: FxHashMap::default(),
45 macro_stack_monitor: SimpleMacroStackMonitor::default(), 45 macro_stack_monitor: MacroStackMonitor::default(),
46 }; 46 };
47 collector.collect(); 47 collector.collect();
48 collector.finish() 48 collector.finish()
49} 49}
50 50
51trait MacroStackMonitor {
52 fn increase(&mut self, macro_def_id: MacroDefId);
53 fn decrease(&mut self, macro_def_id: MacroDefId);
54
55 fn is_poison(&self, macro_def_id: MacroDefId) -> bool;
56}
57
58#[derive(Default)] 51#[derive(Default)]
59struct SimpleMacroStackMonitor { 52struct MacroStackMonitor {
60 counts: FxHashMap<MacroDefId, u32>, 53 counts: FxHashMap<MacroDefId, u32>,
54
55 /// Mainly use for test
56 validator: Option<Box<dyn Fn(u32) -> bool>>,
61} 57}
62 58
63impl MacroStackMonitor for SimpleMacroStackMonitor { 59impl MacroStackMonitor {
64 fn increase(&mut self, macro_def_id: MacroDefId) { 60 fn increase(&mut self, macro_def_id: MacroDefId) {
65 *self.counts.entry(macro_def_id).or_default() += 1; 61 *self.counts.entry(macro_def_id).or_default() += 1;
66 } 62 }
@@ -70,12 +66,18 @@ impl MacroStackMonitor for SimpleMacroStackMonitor {
70 } 66 }
71 67
72 fn is_poison(&self, macro_def_id: MacroDefId) -> bool { 68 fn is_poison(&self, macro_def_id: MacroDefId) -> bool {
73 *self.counts.get(&macro_def_id).unwrap_or(&0) > 100 69 let cur = *self.counts.get(&macro_def_id).unwrap_or(&0);
70
71 if let Some(validator) = &self.validator {
72 validator(cur)
73 } else {
74 cur > 100
75 }
74 } 76 }
75} 77}
76 78
77/// Walks the tree of module recursively 79/// Walks the tree of module recursively
78struct DefCollector<DB, M> { 80struct DefCollector<DB> {
79 db: DB, 81 db: DB,
80 def_map: CrateDefMap, 82 def_map: CrateDefMap,
81 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 83 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
@@ -85,13 +87,12 @@ struct DefCollector<DB, M> {
85 87
86 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 88 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
87 /// To prevent stackoverflow, we add a deep counter here for prevent that. 89 /// To prevent stackoverflow, we add a deep counter here for prevent that.
88 macro_stack_monitor: M, 90 macro_stack_monitor: MacroStackMonitor,
89} 91}
90 92
91impl<'a, DB, M> DefCollector<&'a DB, M> 93impl<'a, DB> DefCollector<&'a DB>
92where 94where
93 DB: DefDatabase, 95 DB: DefDatabase,
94 M: MacroStackMonitor,
95{ 96{
96 fn collect(&mut self) { 97 fn collect(&mut self) {
97 let crate_graph = self.db.crate_graph(); 98 let crate_graph = self.db.crate_graph();
@@ -393,10 +394,9 @@ struct ModCollector<'a, D> {
393 raw_items: &'a raw::RawItems, 394 raw_items: &'a raw::RawItems,
394} 395}
395 396
396impl<DB, M> ModCollector<'_, &'_ mut DefCollector<&'_ DB, M>> 397impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
397where 398where
398 DB: DefDatabase, 399 DB: DefDatabase,
399 M: MacroStackMonitor,
400{ 400{
401 fn collect(&mut self, items: &[raw::RawItem]) { 401 fn collect(&mut self, items: &[raw::RawItem]) {
402 for item in items { 402 for item in items {
@@ -578,31 +578,10 @@ mod tests {
578 use super::*; 578 use super::*;
579 use rustc_hash::FxHashSet; 579 use rustc_hash::FxHashSet;
580 580
581 struct LimitedMacroStackMonitor {
582 count: u32,
583 limit: u32,
584 poison_limit: u32,
585 }
586
587 impl MacroStackMonitor for LimitedMacroStackMonitor {
588 fn increase(&mut self, _: MacroDefId) {
589 self.count += 1;
590 assert!(self.count < self.limit);
591 }
592
593 fn decrease(&mut self, _: MacroDefId) {
594 self.count -= 1;
595 }
596
597 fn is_poison(&self, _: MacroDefId) -> bool {
598 self.count >= self.poison_limit
599 }
600 }
601
602 fn do_collect_defs( 581 fn do_collect_defs(
603 db: &impl DefDatabase, 582 db: &impl DefDatabase,
604 def_map: CrateDefMap, 583 def_map: CrateDefMap,
605 monitor: impl MacroStackMonitor, 584 monitor: MacroStackMonitor,
606 ) -> CrateDefMap { 585 ) -> CrateDefMap {
607 let mut collector = DefCollector { 586 let mut collector = DefCollector {
608 db, 587 db,
@@ -639,7 +618,13 @@ mod tests {
639 } 618 }
640 }; 619 };
641 620
642 do_collect_defs(&db, def_map, LimitedMacroStackMonitor { count: 0, limit, poison_limit }) 621 let mut monitor = MacroStackMonitor::default();
622 monitor.validator = Some(Box::new(move |count| {
623 assert!(count < limit);
624 count >= poison_limit
625 }));
626
627 do_collect_defs(&db, def_map, monitor)
643 } 628 }
644 629
645 #[test] 630 #[test]