@@ -37,45 +37,53 @@ impl Attrs {
37
37
Some ( ProcMacroDef { name : func_name. clone ( ) , kind : ProcMacroKind :: Attr } )
38
38
} else if self . by_key ( "proc_macro_derive" ) . exists ( ) {
39
39
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 } } ) ;
40
42
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) ;
76
45
}
46
+
47
+ def
77
48
} else {
78
49
None
79
50
}
80
51
}
81
52
}
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