44//! resolves imports and expands macros.
55
66use hir_expand:: {
7+ builtin_derive:: find_builtin_derive,
78 builtin_macro:: find_builtin_macro,
89 name:: { self , AsName , Name } ,
9- HirFileId , MacroCallId , MacroDefId , MacroDefKind , MacroFileKind ,
10+ HirFileId , MacroCallId , MacroCallKind , MacroDefId , MacroDefKind , MacroFileKind ,
1011} ;
1112use ra_cfg:: CfgOptions ;
1213use ra_db:: { CrateId , FileId } ;
@@ -58,6 +59,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
5859 glob_imports : FxHashMap :: default ( ) ,
5960 unresolved_imports : Vec :: new ( ) ,
6061 unexpanded_macros : Vec :: new ( ) ,
62+ unexpanded_attribute_macros : Vec :: new ( ) ,
6163 mod_dirs : FxHashMap :: default ( ) ,
6264 macro_stack_monitor : MacroStackMonitor :: default ( ) ,
6365 poison_macros : FxHashSet :: default ( ) ,
@@ -102,6 +104,7 @@ struct DefCollector<'a, DB> {
102104 glob_imports : FxHashMap < LocalModuleId , Vec < ( LocalModuleId , LocalImportId ) > > ,
103105 unresolved_imports : Vec < ( LocalModuleId , LocalImportId , raw:: ImportData ) > ,
104106 unexpanded_macros : Vec < ( LocalModuleId , AstId < ast:: MacroCall > , Path ) > ,
107+ unexpanded_attribute_macros : Vec < ( LocalModuleId , AstId < ast:: ModuleItem > , Path ) > ,
105108 mod_dirs : FxHashMap < LocalModuleId , ModDir > ,
106109
107110 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
@@ -470,6 +473,8 @@ where
470473
471474 fn resolve_macros ( & mut self ) -> ReachedFixedPoint {
472475 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 ( ) ) ;
473478 let mut resolved = Vec :: new ( ) ;
474479 let mut res = ReachedFixedPoint :: Yes ;
475480 macros. retain ( |( module_id, ast_id, path) | {
@@ -482,7 +487,19 @@ where
482487 ) ;
483488
484489 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) ) ;
486503 resolved. push ( ( * module_id, call_id, def) ) ;
487504 res = ReachedFixedPoint :: No ;
488505 return false ;
@@ -492,6 +509,7 @@ where
492509 } ) ;
493510
494511 self . unexpanded_macros = macros;
512+ self . unexpanded_attribute_macros = attribute_macros;
495513
496514 for ( module_id, macro_call_id, macro_def_id) in resolved {
497515 self . collect_macro_expansion ( module_id, macro_call_id, macro_def_id) ;
@@ -500,6 +518,20 @@ where
500518 res
501519 }
502520
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+
503535 fn collect_macro_expansion (
504536 & mut self ,
505537 module_id : LocalModuleId ,
@@ -589,6 +621,9 @@ where
589621 . push ( ( self . module_id , import_id, self . raw_items [ import_id] . clone ( ) ) ) ,
590622 raw:: RawItemKind :: Def ( def) => self . define_def ( & self . raw_items [ def] ) ,
591623 raw:: RawItemKind :: Macro ( mac) => self . collect_macro ( & self . raw_items [ mac] ) ,
624+ raw:: RawItemKind :: AttributeMacro ( att) => {
625+ self . collect_attribute_macro ( & self . raw_items [ att] )
626+ }
592627 raw:: RawItemKind :: Impl ( imp) => {
593628 let module = ModuleId {
594629 krate : self . def_collector . def_map . krate ,
@@ -759,8 +794,8 @@ where
759794 if is_macro_rules ( & mac. path ) {
760795 if let Some ( name) = & mac. name {
761796 let macro_id = MacroDefId {
762- ast_id,
763- krate : self . def_collector . def_map . krate ,
797+ ast_id : Some ( ast_id ) ,
798+ krate : Some ( self . def_collector . def_map . krate ) ,
764799 kind : MacroDefKind :: Declarative ,
765800 } ;
766801 self . def_collector . define_macro ( self . module_id , name. clone ( ) , macro_id, mac. export ) ;
@@ -773,7 +808,8 @@ where
773808 if let Some ( macro_def) = mac. path . as_ident ( ) . and_then ( |name| {
774809 self . def_collector . def_map [ self . module_id ] . scope . get_legacy_macro ( & name)
775810 } ) {
776- let macro_call_id = macro_def. as_call_id ( self . def_collector . db , ast_id) ;
811+ let macro_call_id =
812+ macro_def. as_call_id ( self . def_collector . db , MacroCallKind :: FnLike ( ast_id) ) ;
777813
778814 self . def_collector . collect_macro_expansion ( self . module_id , macro_call_id, macro_def) ;
779815 return ;
@@ -788,6 +824,12 @@ where
788824 self . def_collector . unexpanded_macros . push ( ( self . module_id , ast_id, path) ) ;
789825 }
790826
827+ fn collect_attribute_macro ( & mut self , data : & raw:: AttributeMacroData ) {
828+ let ast_id = AstId :: new ( self . file_id , data. ast_id ) ;
829+ let path = data. path . clone ( ) ;
830+ self . def_collector . unexpanded_attribute_macros . push ( ( self . module_id , ast_id, path) ) ;
831+ }
832+
791833 fn import_all_legacy_macros ( & mut self , module_id : LocalModuleId ) {
792834 let macros = self . def_collector . def_map [ module_id] . scope . legacy_macros . clone ( ) ;
793835 for ( name, macro_) in macros {
@@ -829,6 +871,7 @@ mod tests {
829871 glob_imports : FxHashMap :: default ( ) ,
830872 unresolved_imports : Vec :: new ( ) ,
831873 unexpanded_macros : Vec :: new ( ) ,
874+ unexpanded_attribute_macros : Vec :: new ( ) ,
832875 mod_dirs : FxHashMap :: default ( ) ,
833876 macro_stack_monitor : monitor,
834877 poison_macros : FxHashSet :: default ( ) ,
0 commit comments