@@ -37,6 +37,8 @@ use middle::def_id::DefId;
3737use middle:: ty;
3838
3939use std:: fs:: File ;
40+ use std:: hash:: * ;
41+ use std:: collections:: HashSet ;
4042
4143use syntax:: ast:: { self , NodeId } ;
4244use syntax:: codemap:: * ;
@@ -70,6 +72,14 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
7072 fmt : FmtStrs < ' l , ' tcx > ,
7173
7274 cur_scope : NodeId ,
75+
76+ // Set of macro definition (callee) spans, and the set
77+ // of macro use (callsite) spans. We store these to ensure
78+ // we only write one macro def per unique macro definition, and
79+ // one macro use per unique callsite span.
80+ mac_defs : HashSet < Span > ,
81+ mac_uses : HashSet < Span > ,
82+
7383}
7484
7585impl < ' l , ' tcx > DumpCsvVisitor < ' l , ' tcx > {
@@ -92,6 +102,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
92102 span_utils,
93103 tcx) ,
94104 cur_scope : 0 ,
105+ mac_defs : HashSet :: new ( ) ,
106+ mac_uses : HashSet :: new ( ) ,
95107 }
96108 }
97109
@@ -814,10 +826,41 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
814826 & typ) ;
815827 }
816828 }
829+
830+ /// Extract macro use and definition information from the AST node defined
831+ /// by the given NodeId, using the expansion information from the node's
832+ /// span.
833+ ///
834+ /// If the span is not macro-generated, do nothing, else use callee and
835+ /// callsite spans to record macro definition and use data, using the
836+ /// mac_uses and mac_defs sets to prevent multiples.
837+ fn process_macro_use ( & mut self , span : Span , id : NodeId ) {
838+ let data = match self . save_ctxt . get_macro_use_data ( span, id) {
839+ None => return ,
840+ Some ( data) => data,
841+ } ;
842+ let mut hasher = SipHasher :: new ( ) ;
843+ data. callee_span . hash ( & mut hasher) ;
844+ let hash = hasher. finish ( ) ;
845+ let qualname = format ! ( "{}::{}" , data. name, hash) ;
846+ // Don't write macro definition for imported macros
847+ if !self . mac_defs . contains ( & data. callee_span )
848+ && !data. imported {
849+ self . mac_defs . insert ( data. callee_span ) ;
850+ self . fmt . macro_str ( data. callee_span , data. callee_span ,
851+ data. name . clone ( ) , qualname. clone ( ) ) ;
852+ }
853+ if !self . mac_uses . contains ( & data. span ) {
854+ self . mac_uses . insert ( data. span ) ;
855+ self . fmt . macro_use_str ( data. span , data. span , data. name ,
856+ qualname, data. scope ) ;
857+ }
858+ }
817859}
818860
819861impl < ' l , ' tcx , ' v > Visitor < ' v > for DumpCsvVisitor < ' l , ' tcx > {
820862 fn visit_item ( & mut self , item : & ast:: Item ) {
863+ self . process_macro_use ( item. span , item. id ) ;
821864 match item. node {
822865 ast:: ItemUse ( ref use_item) => {
823866 match use_item. node {
@@ -970,6 +1013,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
9701013 }
9711014
9721015 fn visit_trait_item ( & mut self , trait_item : & ast:: TraitItem ) {
1016+ self . process_macro_use ( trait_item. span , trait_item. id ) ;
9731017 match trait_item. node {
9741018 ast:: ConstTraitItem ( ref ty, Some ( ref expr) ) => {
9751019 self . process_const ( trait_item. id ,
@@ -991,6 +1035,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
9911035 }
9921036
9931037 fn visit_impl_item ( & mut self , impl_item : & ast:: ImplItem ) {
1038+ self . process_macro_use ( impl_item. span , impl_item. id ) ;
9941039 match impl_item. node {
9951040 ast:: ImplItemKind :: Const ( ref ty, ref expr) => {
9961041 self . process_const ( impl_item. id ,
@@ -1012,6 +1057,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
10121057 }
10131058
10141059 fn visit_ty ( & mut self , t : & ast:: Ty ) {
1060+ self . process_macro_use ( t. span , t. id ) ;
10151061 match t. node {
10161062 ast:: TyPath ( _, ref path) => {
10171063 match self . lookup_type_ref ( t. id ) {
@@ -1031,6 +1077,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
10311077 }
10321078
10331079 fn visit_expr ( & mut self , ex : & ast:: Expr ) {
1080+ self . process_macro_use ( ex. span , ex. id ) ;
10341081 match ex. node {
10351082 ast:: ExprCall ( ref _f, ref _args) => {
10361083 // Don't need to do anything for function calls,
@@ -1117,11 +1164,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
11171164 }
11181165 }
11191166
1120- fn visit_mac ( & mut self , _: & ast:: Mac ) {
1121- // Just stop, macros are poison to us.
1167+ fn visit_mac ( & mut self , mac : & ast:: Mac ) {
1168+ // These shouldn't exist in the AST at this point, log a span bug.
1169+ self . sess . span_bug ( mac. span , "macro invocation should have been expanded out of AST" ) ;
11221170 }
11231171
11241172 fn visit_pat ( & mut self , p : & ast:: Pat ) {
1173+ self . process_macro_use ( p. span , p. id ) ;
11251174 self . process_pat ( p) ;
11261175 }
11271176
@@ -1177,10 +1226,13 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
11771226 }
11781227
11791228 fn visit_stmt ( & mut self , s : & ast:: Stmt ) {
1229+ let id = s. node . id ( ) ;
1230+ self . process_macro_use ( s. span , id. unwrap ( ) ) ;
11801231 visit:: walk_stmt ( self , s)
11811232 }
11821233
11831234 fn visit_local ( & mut self , l : & ast:: Local ) {
1235+ self . process_macro_use ( l. span , l. id ) ;
11841236 let value = self . span . snippet ( l. span ) ;
11851237 self . process_var_decl ( & l. pat , value) ;
11861238
0 commit comments