@@ -2,8 +2,9 @@ use proc_macro2::TokenStream;
22use quote:: { format_ident, quote, quote_spanned, ToTokens } ;
33use syn:: spanned:: Spanned ;
44use 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
78} ;
89
910
@@ -78,38 +79,43 @@ struct Attributes {
7879 with : Option < Ident > ,
7980}
8081
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+
8199impl Attributes {
82100 fn parse ( attrs : & [ Attribute ] ) -> Self {
83101 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) ;
92111 }
93112 }
94113 }
95- _ => panic ! ( "Expected #[visit(...)]" ) ,
96114 }
97115 }
98116 out
99117 }
100118
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-
113119 /// Returns the pre and post visit token streams
114120 fn visit ( & self , s : TokenStream ) -> ( Option < TokenStream > , Option < TokenStream > ) {
115121 let pre_visit = self . with . as_ref ( ) . map ( |m| {
0 commit comments