diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 65 |
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 | ||
51 | trait 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)] |
59 | struct SimpleMacroStackMonitor { | 52 | struct 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 | ||
63 | impl MacroStackMonitor for SimpleMacroStackMonitor { | 59 | impl 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(¯o_def_id).unwrap_or(&0) > 100 | 69 | let cur = *self.counts.get(¯o_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 |
78 | struct DefCollector<DB, M> { | 80 | struct 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 | ||
91 | impl<'a, DB, M> DefCollector<&'a DB, M> | 93 | impl<'a, DB> DefCollector<&'a DB> |
92 | where | 94 | where |
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 | ||
396 | impl<DB, M> ModCollector<'_, &'_ mut DefCollector<&'_ DB, M>> | 397 | impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> |
397 | where | 398 | where |
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] |