diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 61 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/raw.rs | 7 |
2 files changed, 42 insertions, 26 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b02364e86..7a5f90327 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -7,8 +7,8 @@ use hir_expand::{ | |||
7 | }; | 7 | }; |
8 | use ra_cfg::CfgOptions; | 8 | use ra_cfg::CfgOptions; |
9 | use ra_db::{CrateId, FileId}; | 9 | use ra_db::{CrateId, FileId}; |
10 | use ra_syntax::{ast, SmolStr}; | 10 | use ra_syntax::ast; |
11 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::{FxHashMap, FxHashSet}; |
12 | use test_utils::tested_by; | 12 | use test_utils::tested_by; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | path::{Path, PathKind}, | 21 | path::{Path, PathKind}, |
22 | per_ns::PerNs, | 22 | per_ns::PerNs, |
23 | AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, | 23 | AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, |
24 | Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, | 24 | Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, |
25 | StructOrUnionId, TraitId, TypeAliasLoc, UnionId, | 25 | StructOrUnionId, TraitId, TypeAliasLoc, UnionId, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -57,6 +57,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
57 | unexpanded_macros: Vec::new(), | 57 | unexpanded_macros: Vec::new(), |
58 | mod_dirs: FxHashMap::default(), | 58 | mod_dirs: FxHashMap::default(), |
59 | macro_stack_monitor: MacroStackMonitor::default(), | 59 | macro_stack_monitor: MacroStackMonitor::default(), |
60 | poison_macros: FxHashSet::default(), | ||
60 | cfg_options, | 61 | cfg_options, |
61 | }; | 62 | }; |
62 | collector.collect(); | 63 | collector.collect(); |
@@ -103,6 +104,17 @@ struct DefCollector<'a, DB> { | |||
103 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly | 104 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly |
104 | /// To prevent stack overflow, we add a deep counter here for prevent that. | 105 | /// To prevent stack overflow, we add a deep counter here for prevent that. |
105 | macro_stack_monitor: MacroStackMonitor, | 106 | macro_stack_monitor: MacroStackMonitor, |
107 | /// Some macros are not well-behavior, which leads to infinite loop | ||
108 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } | ||
109 | /// We mark it down and skip it in collector | ||
110 | /// | ||
111 | /// FIXME: | ||
112 | /// Right now it only handle a poison macro in a single crate, | ||
113 | /// such that if other crate try to call that macro, | ||
114 | /// the whole process will do again until it became poisoned in that crate. | ||
115 | /// We should handle this macro set globally | ||
116 | /// However, do we want to put it as a global variable? | ||
117 | poison_macros: FxHashSet<MacroDefId>, | ||
106 | 118 | ||
107 | cfg_options: &'a CfgOptions, | 119 | cfg_options: &'a CfgOptions, |
108 | } | 120 | } |
@@ -489,7 +501,7 @@ where | |||
489 | macro_call_id: MacroCallId, | 501 | macro_call_id: MacroCallId, |
490 | macro_def_id: MacroDefId, | 502 | macro_def_id: MacroDefId, |
491 | ) { | 503 | ) { |
492 | if self.def_map.poison_macros.contains(¯o_def_id) { | 504 | if self.poison_macros.contains(¯o_def_id) { |
493 | return; | 505 | return; |
494 | } | 506 | } |
495 | 507 | ||
@@ -509,7 +521,7 @@ where | |||
509 | .collect(raw_items.items()); | 521 | .collect(raw_items.items()); |
510 | } else { | 522 | } else { |
511 | log::error!("Too deep macro expansion: {:?}", macro_call_id); | 523 | log::error!("Too deep macro expansion: {:?}", macro_call_id); |
512 | self.def_map.poison_macros.insert(macro_def_id); | 524 | self.poison_macros.insert(macro_def_id); |
513 | } | 525 | } |
514 | 526 | ||
515 | self.macro_stack_monitor.decrease(macro_def_id); | 527 | self.macro_stack_monitor.decrease(macro_def_id); |
@@ -587,8 +599,8 @@ where | |||
587 | } | 599 | } |
588 | 600 | ||
589 | fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { | 601 | fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { |
590 | let path_attr = self.path_attr(attrs); | 602 | let path_attr = attrs.by_key("path").string_value(); |
591 | let is_macro_use = attrs.has_atom("macro_use"); | 603 | let is_macro_use = attrs.by_key("macro_use").exists(); |
592 | match module { | 604 | match module { |
593 | // inline module, just recurse | 605 | // inline module, just recurse |
594 | raw::ModuleData::Definition { name, items, ast_id } => { | 606 | raw::ModuleData::Definition { name, items, ast_id } => { |
@@ -703,7 +715,10 @@ where | |||
703 | PerNs::values(def.into()) | 715 | PerNs::values(def.into()) |
704 | } | 716 | } |
705 | raw::DefKind::Static(ast_id) => { | 717 | raw::DefKind::Static(ast_id) => { |
706 | PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) | 718 | let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } |
719 | .intern(self.def_collector.db); | ||
720 | |||
721 | PerNs::values(def.into()) | ||
707 | } | 722 | } |
708 | raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), | 723 | raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), |
709 | raw::DefKind::TypeAlias(ast_id) => { | 724 | raw::DefKind::TypeAlias(ast_id) => { |
@@ -781,11 +796,11 @@ where | |||
781 | } | 796 | } |
782 | 797 | ||
783 | fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | 798 | fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { |
784 | attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) | 799 | // FIXME: handle cfg_attr :-) |
785 | } | 800 | attrs |
786 | 801 | .by_key("cfg") | |
787 | fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> { | 802 | .tt_values() |
788 | attrs.iter().find_map(|attr| attr.as_path()) | 803 | .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false)) |
789 | } | 804 | } |
790 | } | 805 | } |
791 | 806 | ||
@@ -807,7 +822,7 @@ mod tests { | |||
807 | db: &impl DefDatabase, | 822 | db: &impl DefDatabase, |
808 | def_map: CrateDefMap, | 823 | def_map: CrateDefMap, |
809 | monitor: MacroStackMonitor, | 824 | monitor: MacroStackMonitor, |
810 | ) -> CrateDefMap { | 825 | ) -> (CrateDefMap, FxHashSet<MacroDefId>) { |
811 | let mut collector = DefCollector { | 826 | let mut collector = DefCollector { |
812 | db, | 827 | db, |
813 | def_map, | 828 | def_map, |
@@ -816,13 +831,18 @@ mod tests { | |||
816 | unexpanded_macros: Vec::new(), | 831 | unexpanded_macros: Vec::new(), |
817 | mod_dirs: FxHashMap::default(), | 832 | mod_dirs: FxHashMap::default(), |
818 | macro_stack_monitor: monitor, | 833 | macro_stack_monitor: monitor, |
834 | poison_macros: FxHashSet::default(), | ||
819 | cfg_options: &CfgOptions::default(), | 835 | cfg_options: &CfgOptions::default(), |
820 | }; | 836 | }; |
821 | collector.collect(); | 837 | collector.collect(); |
822 | collector.finish() | 838 | (collector.def_map, collector.poison_macros) |
823 | } | 839 | } |
824 | 840 | ||
825 | fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { | 841 | fn do_limited_resolve( |
842 | code: &str, | ||
843 | limit: u32, | ||
844 | poison_limit: u32, | ||
845 | ) -> (CrateDefMap, FxHashSet<MacroDefId>) { | ||
826 | let (db, _file_id) = TestDB::with_single_file(&code); | 846 | let (db, _file_id) = TestDB::with_single_file(&code); |
827 | let krate = db.test_crate(); | 847 | let krate = db.test_crate(); |
828 | 848 | ||
@@ -837,7 +857,6 @@ mod tests { | |||
837 | prelude: None, | 857 | prelude: None, |
838 | root, | 858 | root, |
839 | modules, | 859 | modules, |
840 | poison_macros: FxHashSet::default(), | ||
841 | diagnostics: Vec::new(), | 860 | diagnostics: Vec::new(), |
842 | } | 861 | } |
843 | }; | 862 | }; |
@@ -867,7 +886,7 @@ foo!(KABOOM); | |||
867 | 886 | ||
868 | #[test] | 887 | #[test] |
869 | fn test_macro_expand_poisoned() { | 888 | fn test_macro_expand_poisoned() { |
870 | let def = do_limited_resolve( | 889 | let (_, poison_macros) = do_limited_resolve( |
871 | r#" | 890 | r#" |
872 | macro_rules! foo { | 891 | macro_rules! foo { |
873 | ($ty:ty) => { foo!($ty); } | 892 | ($ty:ty) => { foo!($ty); } |
@@ -878,12 +897,12 @@ foo!(KABOOM); | |||
878 | 16, | 897 | 16, |
879 | ); | 898 | ); |
880 | 899 | ||
881 | assert_eq!(def.poison_macros.len(), 1); | 900 | assert_eq!(poison_macros.len(), 1); |
882 | } | 901 | } |
883 | 902 | ||
884 | #[test] | 903 | #[test] |
885 | fn test_macro_expand_normal() { | 904 | fn test_macro_expand_normal() { |
886 | let def = do_limited_resolve( | 905 | let (_, poison_macros) = do_limited_resolve( |
887 | r#" | 906 | r#" |
888 | macro_rules! foo { | 907 | macro_rules! foo { |
889 | ($ident:ident) => { struct $ident {} } | 908 | ($ident:ident) => { struct $ident {} } |
@@ -894,6 +913,6 @@ foo!(Bar); | |||
894 | 16, | 913 | 16, |
895 | ); | 914 | ); |
896 | 915 | ||
897 | assert_eq!(def.poison_macros.len(), 0); | 916 | assert_eq!(poison_macros.len(), 0); |
898 | } | 917 | } |
899 | } | 918 | } |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 552cbe544..198578753 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -17,10 +17,7 @@ use ra_syntax::{ | |||
17 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | attr::{Attr, Attrs}, | 20 | attr::Attrs, db::DefDatabase, path::Path, FileAstId, HirFileId, LocalImportId, Source, |
21 | db::DefDatabase, | ||
22 | path::Path, | ||
23 | FileAstId, HirFileId, LocalImportId, Source, | ||
24 | }; | 21 | }; |
25 | 22 | ||
26 | /// `RawItems` is a set of top-level items in a file (except for impls). | 23 | /// `RawItems` is a set of top-level items in a file (except for impls). |
@@ -407,6 +404,6 @@ impl RawItemsCollector { | |||
407 | } | 404 | } |
408 | 405 | ||
409 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | 406 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { |
410 | Attr::from_attrs_owner(item, &self.hygiene) | 407 | Attrs::new(item, &self.hygiene) |
411 | } | 408 | } |
412 | } | 409 | } |