@@ -37,45 +37,53 @@ impl Attrs {
3737 Some ( ProcMacroDef { name : func_name. clone ( ) , kind : ProcMacroKind :: Attr } )
3838 } else if self . by_key ( "proc_macro_derive" ) . exists ( ) {
3939 let derive = self . by_key ( "proc_macro_derive" ) . tt_values ( ) . next ( ) ?;
40+ let def = parse_macro_name_and_helper_attrs ( & derive. token_trees )
41+ . map ( |( name, helpers) | ProcMacroDef { name, kind : ProcMacroKind :: CustomDerive { helpers } } ) ;
4042
41- match & * derive. token_trees {
42- // `#[proc_macro_derive(Trait)]`
43- [ TokenTree :: Leaf ( Leaf :: Ident ( trait_name) ) ] => Some ( ProcMacroDef {
44- name : trait_name. as_name ( ) ,
45- kind : ProcMacroKind :: CustomDerive { helpers : Box :: new ( [ ] ) } ,
46- } ) ,
47-
48- // `#[proc_macro_derive(Trait, attributes(helper1, helper2, ...))]`
49- [
50- TokenTree :: Leaf ( Leaf :: Ident ( trait_name) ) ,
51- TokenTree :: Leaf ( Leaf :: Punct ( comma) ) ,
52- TokenTree :: Leaf ( Leaf :: Ident ( attributes) ) ,
53- TokenTree :: Subtree ( helpers)
54- ] if comma. char == ',' && attributes. text == "attributes" =>
55- {
56- let helpers = helpers. token_trees . iter ( )
57- . filter ( |tt| !matches ! ( tt, TokenTree :: Leaf ( Leaf :: Punct ( comma) ) if comma. char == ',' ) )
58- . map ( |tt| {
59- match tt {
60- TokenTree :: Leaf ( Leaf :: Ident ( helper) ) => Some ( helper. as_name ( ) ) ,
61- _ => None
62- }
63- } )
64- . collect :: < Option < Box < [ _ ] > > > ( ) ?;
65-
66- Some ( ProcMacroDef {
67- name : trait_name. as_name ( ) ,
68- kind : ProcMacroKind :: CustomDerive { helpers } ,
69- } )
70- }
71-
72- _ => {
73- tracing:: trace!( "malformed `#[proc_macro_derive]`: {}" , derive) ;
74- None
75- }
43+ if def. is_none ( ) {
44+ tracing:: trace!( "malformed `#[proc_macro_derive]`: {}" , derive) ;
7645 }
46+
47+ def
7748 } else {
7849 None
7950 }
8051 }
8152}
53+
54+ // This fn is intended for `#[proc_macro_derive(..)]` and `#[rustc_builtin_macro(..)]`, which have
55+ // the same strucuture.
56+ #[ rustfmt:: skip]
57+ pub ( crate ) fn parse_macro_name_and_helper_attrs ( tt : & [ TokenTree ] ) -> Option < ( Name , Box < [ Name ] > ) > {
58+ match tt {
59+ // `#[proc_macro_derive(Trait)]`
60+ // `#[rustc_builtin_macro(Trait)]`
61+ [ TokenTree :: Leaf ( Leaf :: Ident ( trait_name) ) ] => Some ( ( trait_name. as_name ( ) , Box :: new ( [ ] ) ) ) ,
62+
63+ // `#[proc_macro_derive(Trait, attributes(helper1, helper2, ...))]`
64+ // `#[rustc_builtin_macro(Trait, attributes(helper1, helper2, ...))]`
65+ [
66+ TokenTree :: Leaf ( Leaf :: Ident ( trait_name) ) ,
67+ TokenTree :: Leaf ( Leaf :: Punct ( comma) ) ,
68+ TokenTree :: Leaf ( Leaf :: Ident ( attributes) ) ,
69+ TokenTree :: Subtree ( helpers)
70+ ] if comma. char == ',' && attributes. text == "attributes" =>
71+ {
72+ let helpers = helpers
73+ . token_trees
74+ . iter ( )
75+ . filter (
76+ |tt| !matches ! ( tt, TokenTree :: Leaf ( Leaf :: Punct ( comma) ) if comma. char == ',' ) ,
77+ )
78+ . map ( |tt| match tt {
79+ TokenTree :: Leaf ( Leaf :: Ident ( helper) ) => Some ( helper. as_name ( ) ) ,
80+ _ => None ,
81+ } )
82+ . collect :: < Option < Box < [ _ ] > > > ( ) ?;
83+
84+ Some ( ( trait_name. as_name ( ) , helpers) )
85+ }
86+
87+ _ => None ,
88+ }
89+ }
0 commit comments