aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs61
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs7
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};
8use ra_cfg::CfgOptions; 8use ra_cfg::CfgOptions;
9use ra_db::{CrateId, FileId}; 9use ra_db::{CrateId, FileId};
10use ra_syntax::{ast, SmolStr}; 10use ra_syntax::ast;
11use rustc_hash::FxHashMap; 11use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{ 14use 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(&macro_def_id) { 504 if self.poison_macros.contains(&macro_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::{
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{ 19use 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}