4
4
//! resolves imports and expands macros.
5
5
6
6
use hir_expand:: {
7
+ builtin_derive:: find_builtin_derive,
7
8
builtin_macro:: find_builtin_macro,
8
9
name:: { self , AsName , Name } ,
9
- HirFileId , MacroCallId , MacroDefId , MacroDefKind , MacroFileKind ,
10
+ HirFileId , MacroCallId , MacroCallKind , MacroDefId , MacroDefKind , MacroFileKind ,
10
11
} ;
11
12
use ra_cfg:: CfgOptions ;
12
13
use ra_db:: { CrateId , FileId } ;
@@ -58,6 +59,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
58
59
glob_imports : FxHashMap :: default ( ) ,
59
60
unresolved_imports : Vec :: new ( ) ,
60
61
unexpanded_macros : Vec :: new ( ) ,
62
+ unexpanded_attribute_macros : Vec :: new ( ) ,
61
63
mod_dirs : FxHashMap :: default ( ) ,
62
64
macro_stack_monitor : MacroStackMonitor :: default ( ) ,
63
65
poison_macros : FxHashSet :: default ( ) ,
@@ -102,6 +104,7 @@ struct DefCollector<'a, DB> {
102
104
glob_imports : FxHashMap < LocalModuleId , Vec < ( LocalModuleId , LocalImportId ) > > ,
103
105
unresolved_imports : Vec < ( LocalModuleId , LocalImportId , raw:: ImportData ) > ,
104
106
unexpanded_macros : Vec < ( LocalModuleId , AstId < ast:: MacroCall > , Path ) > ,
107
+ unexpanded_attribute_macros : Vec < ( LocalModuleId , AstId < ast:: ModuleItem > , Path ) > ,
105
108
mod_dirs : FxHashMap < LocalModuleId , ModDir > ,
106
109
107
110
/// Some macro use `$tt:tt which mean we have to handle the macro perfectly
@@ -470,6 +473,8 @@ where
470
473
471
474
fn resolve_macros ( & mut self ) -> ReachedFixedPoint {
472
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
478
let mut resolved = Vec :: new ( ) ;
474
479
let mut res = ReachedFixedPoint :: Yes ;
475
480
macros. retain ( |( module_id, ast_id, path) | {
@@ -482,7 +487,19 @@ where
482
487
) ;
483
488
484
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
503
resolved. push ( ( * module_id, call_id, def) ) ;
487
504
res = ReachedFixedPoint :: No ;
488
505
return false ;
@@ -492,6 +509,7 @@ where
492
509
} ) ;
493
510
494
511
self . unexpanded_macros = macros;
512
+ self . unexpanded_attribute_macros = attribute_macros;
495
513
496
514
for ( module_id, macro_call_id, macro_def_id) in resolved {
497
515
self . collect_macro_expansion ( module_id, macro_call_id, macro_def_id) ;
@@ -500,6 +518,20 @@ where
500
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
535
fn collect_macro_expansion (
504
536
& mut self ,
505
537
module_id : LocalModuleId ,
@@ -587,7 +619,9 @@ where
587
619
. def_collector
588
620
. unresolved_imports
589
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
625
raw:: RawItemKind :: Macro ( mac) => self . collect_macro ( & self . raw_items [ mac] ) ,
592
626
raw:: RawItemKind :: Impl ( imp) => {
593
627
let module = ModuleId {
@@ -682,10 +716,16 @@ where
682
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
720
let module = ModuleId { krate : self . def_collector . def_map . krate , local_id : self . module_id } ;
687
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
729
let name = def. name . clone ( ) ;
690
730
let def: PerNs = match def. kind {
691
731
raw:: DefKind :: Function ( ast_id) => {
@@ -736,6 +776,23 @@ where
736
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
796
fn collect_macro ( & mut self , mac : & raw:: MacroData ) {
740
797
let ast_id = AstId :: new ( self . file_id , mac. ast_id ) ;
741
798
@@ -759,8 +816,8 @@ where
759
816
if is_macro_rules ( & mac. path ) {
760
817
if let Some ( name) = & mac. name {
761
818
let macro_id = MacroDefId {
762
- ast_id,
763
- krate : self . def_collector . def_map . krate ,
819
+ ast_id : Some ( ast_id ) ,
820
+ krate : Some ( self . def_collector . def_map . krate ) ,
764
821
kind : MacroDefKind :: Declarative ,
765
822
} ;
766
823
self . def_collector . define_macro ( self . module_id , name. clone ( ) , macro_id, mac. export ) ;
@@ -773,7 +830,8 @@ where
773
830
if let Some ( macro_def) = mac. path . as_ident ( ) . and_then ( |name| {
774
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
836
self . def_collector . collect_macro_expansion ( self . module_id , macro_call_id, macro_def) ;
779
837
return ;
@@ -829,6 +887,7 @@ mod tests {
829
887
glob_imports : FxHashMap :: default ( ) ,
830
888
unresolved_imports : Vec :: new ( ) ,
831
889
unexpanded_macros : Vec :: new ( ) ,
890
+ unexpanded_attribute_macros : Vec :: new ( ) ,
832
891
mod_dirs : FxHashMap :: default ( ) ,
833
892
macro_stack_monitor : monitor,
834
893
poison_macros : FxHashSet :: default ( ) ,
0 commit comments