@@ -2,8 +2,9 @@ use proc_macro2::TokenStream;
2
2
use quote:: { format_ident, quote, quote_spanned, ToTokens } ;
3
3
use syn:: spanned:: Spanned ;
4
4
use syn:: {
5
- parse_macro_input, parse_quote, Attribute , Data , DeriveInput , Fields , GenericParam , Generics ,
6
- Ident , Index , Lit , Meta , MetaNameValue , NestedMeta ,
5
+ parse:: { Parse , ParseStream } ,
6
+ parse_macro_input, parse_quote, Attribute , Data , DeriveInput ,
7
+ Fields , GenericParam , Generics , Ident , Index , LitStr , Meta , Token
7
8
} ;
8
9
9
10
@@ -78,38 +79,43 @@ struct Attributes {
78
79
with : Option < Ident > ,
79
80
}
80
81
82
+ struct WithIdent {
83
+ with : Option < Ident > ,
84
+ }
85
+ impl Parse for WithIdent {
86
+ fn parse ( input : ParseStream ) -> Result < Self , syn:: Error > {
87
+ let mut result = WithIdent { with : None } ;
88
+ let ident = input. parse :: < Ident > ( ) ?;
89
+ if ident != "with" {
90
+ return Err ( syn:: Error :: new ( ident. span ( ) , "Expected identifier to be `with`" ) ) ;
91
+ }
92
+ input. parse :: < Token ! ( =) > ( ) ?;
93
+ let s = input. parse :: < LitStr > ( ) ?;
94
+ result. with = Some ( format_ident ! ( "{}" , s. value( ) , span = s. span( ) ) ) ;
95
+ Ok ( result)
96
+ }
97
+ }
98
+
81
99
impl Attributes {
82
100
fn parse ( attrs : & [ Attribute ] ) -> Self {
83
101
let mut out = Self :: default ( ) ;
84
- for attr in attrs. iter ( ) . filter ( |a| a. path . is_ident ( "visit" ) ) {
85
- let meta = attr. parse_meta ( ) . expect ( "visit attribute" ) ;
86
- match meta {
87
- Meta :: List ( l) => {
88
- for nested in & l. nested {
89
- match nested {
90
- NestedMeta :: Meta ( Meta :: NameValue ( v) ) => out. parse_name_value ( v) ,
91
- _ => panic ! ( "Expected #[visit(key = \" value\" )]" ) ,
102
+ for attr in attrs {
103
+ if let Meta :: List ( ref metalist) = attr. meta {
104
+ if metalist. path . is_ident ( "visit" ) {
105
+ match syn:: parse2 :: < WithIdent > ( metalist. tokens . clone ( ) ) {
106
+ Ok ( with_ident) => {
107
+ out. with = with_ident. with ;
108
+ }
109
+ Err ( e) => {
110
+ panic ! ( "{}" , e) ;
92
111
}
93
112
}
94
113
}
95
- _ => panic ! ( "Expected #[visit(...)]" ) ,
96
114
}
97
115
}
98
116
out
99
117
}
100
118
101
- /// Updates self with a name value attribute
102
- fn parse_name_value ( & mut self , v : & MetaNameValue ) {
103
- if v. path . is_ident ( "with" ) {
104
- match & v. lit {
105
- Lit :: Str ( s) => self . with = Some ( format_ident ! ( "{}" , s. value( ) , span = s. span( ) ) ) ,
106
- _ => panic ! ( "Expected a string value, got {}" , v. lit. to_token_stream( ) ) ,
107
- }
108
- return ;
109
- }
110
- panic ! ( "Unrecognised kv attribute {}" , v. path. to_token_stream( ) )
111
- }
112
-
113
119
/// Returns the pre and post visit token streams
114
120
fn visit ( & self , s : TokenStream ) -> ( Option < TokenStream > , Option < TokenStream > ) {
115
121
let pre_visit = self . with . as_ref ( ) . map ( |m| {
0 commit comments