@@ -17,16 +17,14 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}
1717use rustc:: hir:: def:: { Def , Export } ;
1818use rustc:: hir:: map:: { self , DefCollector } ;
1919use rustc:: ty;
20- use std:: cell:: Cell ;
21- use std:: rc:: Rc ;
2220use syntax:: ast:: { self , Name , Ident } ;
23- use syntax:: attr;
21+ use syntax:: attr:: { self , HasAttrs } ;
2422use syntax:: errors:: DiagnosticBuilder ;
25- use syntax:: ext:: base:: { self , Determinacy , MultiModifier , MultiDecorator } ;
26- use syntax:: ext:: base:: { Resolver as SyntaxResolver , SyntaxExtension } ;
27- use syntax:: ext:: base:: MacroKind ;
28- use syntax:: ext:: expand:: Expansion ;
23+ use syntax:: ext:: base:: { self , Annotatable , Determinacy , MultiModifier , MultiDecorator } ;
24+ use syntax:: ext:: base:: { MacroKind , SyntaxExtension , Resolver as SyntaxResolver } ;
25+ use syntax:: ext:: expand:: { Expansion , ExpansionKind , Invocation , InvocationKind , find_attr_invoc} ;
2926use syntax:: ext:: hygiene:: Mark ;
27+ use syntax:: ext:: placeholders:: placeholder;
3028use syntax:: ext:: tt:: macro_rules;
3129use syntax:: feature_gate:: { self , emit_feature_err, GateIssue } ;
3230use syntax:: fold:: { self , Folder } ;
@@ -35,6 +33,10 @@ use syntax::symbol::{Symbol, keywords};
3533use syntax:: util:: lev_distance:: find_best_match_for_name;
3634use syntax_pos:: { Span , DUMMY_SP } ;
3735
36+ use std:: cell:: Cell ;
37+ use std:: mem;
38+ use std:: rc:: Rc ;
39+
3840#[ derive( Clone ) ]
3941pub struct InvocationData < ' a > {
4042 pub module : Cell < Module < ' a > > ,
@@ -235,8 +237,64 @@ impl<'a> base::Resolver for Resolver<'a> {
235237 None
236238 }
237239
238- fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind ,
239- force : bool ) -> Result < Rc < SyntaxExtension > , Determinacy > {
240+ fn resolve_invoc ( & mut self , invoc : & mut Invocation , scope : Mark , force : bool )
241+ -> Result < Option < Rc < SyntaxExtension > > , Determinacy > {
242+ let ( attr, traits, item) = match invoc. kind {
243+ InvocationKind :: Attr { attr : None , .. } => return Ok ( None ) ,
244+ InvocationKind :: Attr { ref mut attr, ref traits, ref mut item } => ( attr, traits, item) ,
245+ InvocationKind :: Bang { ref mac, .. } => {
246+ return self . resolve_macro ( scope, & mac. node . path , MacroKind :: Bang , force) . map ( Some ) ;
247+ }
248+ InvocationKind :: Derive { name, span, .. } => {
249+ let path = ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( name) ) ;
250+ return self . resolve_macro ( scope, & path, MacroKind :: Derive , force) . map ( Some ) ;
251+ }
252+ } ;
253+
254+ let ( attr_name, path) = {
255+ let attr = attr. as_ref ( ) . unwrap ( ) ;
256+ ( attr. name ( ) , ast:: Path :: from_ident ( attr. span , Ident :: with_empty_ctxt ( attr. name ( ) ) ) )
257+ } ;
258+
259+ let mut determined = true ;
260+ match self . resolve_macro ( scope, & path, MacroKind :: Attr , force) {
261+ Ok ( ext) => return Ok ( Some ( ext) ) ,
262+ Err ( Determinacy :: Undetermined ) => determined = false ,
263+ Err ( Determinacy :: Determined ) if force => return Err ( Determinacy :: Determined ) ,
264+ Err ( Determinacy :: Determined ) => { }
265+ }
266+
267+ for & ( name, span) in traits {
268+ let path = ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( name) ) ;
269+ match self . resolve_macro ( scope, & path, MacroKind :: Derive , force) {
270+ Ok ( ext) => if let SyntaxExtension :: ProcMacroDerive ( _, ref inert_attrs) = * ext {
271+ if inert_attrs. contains ( & attr_name) {
272+ // FIXME(jseyfried) Avoid `mem::replace` here.
273+ let dummy_item = placeholder ( ExpansionKind :: Items , ast:: DUMMY_NODE_ID )
274+ . make_items ( ) . pop ( ) . unwrap ( ) ;
275+ let dummy_item = Annotatable :: Item ( dummy_item) ;
276+ * item = mem:: replace ( item, dummy_item) . map_attrs ( |mut attrs| {
277+ let inert_attr = attr. take ( ) . unwrap ( ) ;
278+ attr:: mark_known ( & inert_attr) ;
279+ if self . proc_macro_enabled {
280+ * attr = find_attr_invoc ( & mut attrs) ;
281+ }
282+ attrs. push ( inert_attr) ;
283+ attrs
284+ } ) ;
285+ }
286+ return Err ( Determinacy :: Undetermined ) ;
287+ } ,
288+ Err ( Determinacy :: Undetermined ) => determined = false ,
289+ Err ( Determinacy :: Determined ) => { }
290+ }
291+ }
292+
293+ Err ( if determined { Determinacy :: Determined } else { Determinacy :: Undetermined } )
294+ }
295+
296+ fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind , force : bool )
297+ -> Result < Rc < SyntaxExtension > , Determinacy > {
240298 let ast:: Path { ref segments, span } = * path;
241299 if segments. iter ( ) . any ( |segment| segment. parameters . is_some ( ) ) {
242300 let kind =
0 commit comments