aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres/collector.rs')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs73
1 files changed, 66 insertions, 7 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 9d948d4f4..08693cb13 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -4,9 +4,10 @@
4//! resolves imports and expands macros. 4//! resolves imports and expands macros.
5 5
6use hir_expand::{ 6use hir_expand::{
7 builtin_derive::find_builtin_derive,
7 builtin_macro::find_builtin_macro, 8 builtin_macro::find_builtin_macro,
8 name::{self, AsName, Name}, 9 name::{self, AsName, Name},
9 HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind, 10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, MacroFileKind,
10}; 11};
11use ra_cfg::CfgOptions; 12use ra_cfg::CfgOptions;
12use ra_db::{CrateId, FileId}; 13use ra_db::{CrateId, FileId};
@@ -58,6 +59,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
58 glob_imports: FxHashMap::default(), 59 glob_imports: FxHashMap::default(),
59 unresolved_imports: Vec::new(), 60 unresolved_imports: Vec::new(),
60 unexpanded_macros: Vec::new(), 61 unexpanded_macros: Vec::new(),
62 unexpanded_attribute_macros: Vec::new(),
61 mod_dirs: FxHashMap::default(), 63 mod_dirs: FxHashMap::default(),
62 macro_stack_monitor: MacroStackMonitor::default(), 64 macro_stack_monitor: MacroStackMonitor::default(),
63 poison_macros: FxHashSet::default(), 65 poison_macros: FxHashSet::default(),
@@ -102,6 +104,7 @@ struct DefCollector<'a, DB> {
102 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>, 104 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
103 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>, 105 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>,
104 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>, 106 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>,
107 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, Path)>,
105 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 108 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
106 109
107 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 110 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
@@ -470,6 +473,8 @@ where
470 473
471 fn resolve_macros(&mut self) -> ReachedFixedPoint { 474 fn resolve_macros(&mut self) -> ReachedFixedPoint {
472 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 475 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
476 let mut attribute_macros =
477 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
473 let mut resolved = Vec::new(); 478 let mut resolved = Vec::new();
474 let mut res = ReachedFixedPoint::Yes; 479 let mut res = ReachedFixedPoint::Yes;
475 macros.retain(|(module_id, ast_id, path)| { 480 macros.retain(|(module_id, ast_id, path)| {
@@ -482,7 +487,19 @@ where
482 ); 487 );
483 488
484 if let Some(def) = resolved_res.resolved_def.take_macros() { 489 if let Some(def) = resolved_res.resolved_def.take_macros() {
485 let call_id = def.as_call_id(self.db, *ast_id); 490 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(*ast_id));
491 resolved.push((*module_id, call_id, def));
492 res = ReachedFixedPoint::No;
493 return false;
494 }
495
496 true
497 });
498 attribute_macros.retain(|(module_id, ast_id, path)| {
499 let resolved_res = self.resolve_attribute_macro(path);
500
501 if let Some(def) = resolved_res {
502 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
486 resolved.push((*module_id, call_id, def)); 503 resolved.push((*module_id, call_id, def));
487 res = ReachedFixedPoint::No; 504 res = ReachedFixedPoint::No;
488 return false; 505 return false;
@@ -492,6 +509,7 @@ where
492 }); 509 });
493 510
494 self.unexpanded_macros = macros; 511 self.unexpanded_macros = macros;
512 self.unexpanded_attribute_macros = attribute_macros;
495 513
496 for (module_id, macro_call_id, macro_def_id) in resolved { 514 for (module_id, macro_call_id, macro_def_id) in resolved {
497 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id); 515 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id);
@@ -500,6 +518,20 @@ where
500 res 518 res
501 } 519 }
502 520
521 fn resolve_attribute_macro(&self, path: &Path) -> Option<MacroDefId> {
522 // FIXME this is currently super hacky, just enough to support the
523 // built-in derives
524 if let Some(name) = path.as_ident() {
525 // FIXME this should actually be handled with the normal name
526 // resolution; the std lib defines built-in stubs for the derives,
527 // but these are new-style `macro`s, which we don't support yet
528 if let Some(def_id) = find_builtin_derive(name) {
529 return Some(def_id);
530 }
531 }
532 None
533 }
534
503 fn collect_macro_expansion( 535 fn collect_macro_expansion(
504 &mut self, 536 &mut self,
505 module_id: LocalModuleId, 537 module_id: LocalModuleId,
@@ -587,7 +619,9 @@ where
587 .def_collector 619 .def_collector
588 .unresolved_imports 620 .unresolved_imports
589 .push((self.module_id, import_id, self.raw_items[import_id].clone())), 621 .push((self.module_id, import_id, self.raw_items[import_id].clone())),
590 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), 622 raw::RawItemKind::Def(def) => {
623 self.define_def(&self.raw_items[def], &item.attrs)
624 }
591 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 625 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
592 raw::RawItemKind::Impl(imp) => { 626 raw::RawItemKind::Impl(imp) => {
593 let module = ModuleId { 627 let module = ModuleId {
@@ -682,10 +716,16 @@ where
682 res 716 res
683 } 717 }
684 718
685 fn define_def(&mut self, def: &raw::DefData) { 719 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
686 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; 720 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
687 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 721 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
688 722
723 // FIXME: check attrs to see if this is an attribute macro invocation;
724 // in which case we don't add the invocation, just a single attribute
725 // macro invocation
726
727 self.collect_derives(attrs, def);
728
689 let name = def.name.clone(); 729 let name = def.name.clone();
690 let def: PerNs = match def.kind { 730 let def: PerNs = match def.kind {
691 raw::DefKind::Function(ast_id) => { 731 raw::DefKind::Function(ast_id) => {
@@ -736,6 +776,23 @@ where
736 self.def_collector.update(self.module_id, None, &[(name, resolution)]) 776 self.def_collector.update(self.module_id, None, &[(name, resolution)])
737 } 777 }
738 778
779 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
780 for derive_subtree in attrs.by_key("derive").tt_values() {
781 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
782 for tt in &derive_subtree.token_trees {
783 let ident = match &tt {
784 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
785 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
786 _ => continue, // anything else would be an error (which we currently ignore)
787 };
788 let path = Path::from_tt_ident(ident);
789
790 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
791 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
792 }
793 }
794 }
795
739 fn collect_macro(&mut self, mac: &raw::MacroData) { 796 fn collect_macro(&mut self, mac: &raw::MacroData) {
740 let ast_id = AstId::new(self.file_id, mac.ast_id); 797 let ast_id = AstId::new(self.file_id, mac.ast_id);
741 798
@@ -759,8 +816,8 @@ where
759 if is_macro_rules(&mac.path) { 816 if is_macro_rules(&mac.path) {
760 if let Some(name) = &mac.name { 817 if let Some(name) = &mac.name {
761 let macro_id = MacroDefId { 818 let macro_id = MacroDefId {
762 ast_id, 819 ast_id: Some(ast_id),
763 krate: self.def_collector.def_map.krate, 820 krate: Some(self.def_collector.def_map.krate),
764 kind: MacroDefKind::Declarative, 821 kind: MacroDefKind::Declarative,
765 }; 822 };
766 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 823 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
@@ -773,7 +830,8 @@ where
773 if let Some(macro_def) = mac.path.as_ident().and_then(|name| { 830 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
774 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 831 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
775 }) { 832 }) {
776 let macro_call_id = macro_def.as_call_id(self.def_collector.db, ast_id); 833 let macro_call_id =
834 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
777 835
778 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); 836 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def);
779 return; 837 return;
@@ -829,6 +887,7 @@ mod tests {
829 glob_imports: FxHashMap::default(), 887 glob_imports: FxHashMap::default(),
830 unresolved_imports: Vec::new(), 888 unresolved_imports: Vec::new(),
831 unexpanded_macros: Vec::new(), 889 unexpanded_macros: Vec::new(),
890 unexpanded_attribute_macros: Vec::new(),
832 mod_dirs: FxHashMap::default(), 891 mod_dirs: FxHashMap::default(),
833 macro_stack_monitor: monitor, 892 macro_stack_monitor: monitor,
834 poison_macros: FxHashSet::default(), 893 poison_macros: FxHashSet::default(),