@@ -209,11 +209,11 @@ use proc_macro::TokenStream;
209
209
use proc_macro2:: TokenStream as TokenStream2 ;
210
210
use proc_macro_error2:: { abort, abort_call_site, proc_macro_error} ;
211
211
use syn:: {
212
- parse_macro_input, punctuated:: Punctuated , spanned:: Spanned , Attribute , Data , DataStruct ,
213
- DeriveInput , Fields , Meta , Token ,
212
+ parse_macro_input, parse_str , punctuated:: Punctuated , spanned:: Spanned , Attribute , Data ,
213
+ DataStruct , DeriveInput , Fields , ItemImpl , Meta , Token ,
214
214
} ;
215
215
216
- use crate :: generate:: { GenMode , GenParams } ;
216
+ use crate :: generate:: { expr_to_string , GenMode , GenParams } ;
217
217
218
218
mod generate;
219
219
@@ -272,21 +272,47 @@ pub fn with_setters(input: TokenStream) -> TokenStream {
272
272
}
273
273
274
274
fn make_params ( attrs : & [ Attribute ] , mode : GenMode ) -> GenParams {
275
+ let mut impl_attrs = vec ! [ ] ;
275
276
GenParams {
276
277
mode,
277
- global_attr : attrs. iter ( ) . filter_map ( |v| parse_attr ( v, mode) ) . last ( ) ,
278
+ global_attr : attrs
279
+ . iter ( )
280
+ . filter_map ( |v| {
281
+ let ( attr, impl_attrs_exist) = parse_attr ( v, mode, true ) ;
282
+ if let Some ( Meta :: NameValue ( code) ) = & impl_attrs_exist {
283
+ match expr_to_string ( & code. value ) {
284
+ Some ( code_str) => {
285
+ match parse_str :: < ItemImpl > ( & format ! ( "{} impl _ {{}}" , code_str) ) {
286
+ Ok ( parsed_impl) => impl_attrs. extend ( parsed_impl. attrs ) ,
287
+ Err ( _) => abort ! (
288
+ code. value. span( ) ,
289
+ "Syntax error, expected attributes like #[..]."
290
+ ) ,
291
+ }
292
+ }
293
+ None => abort ! ( code. value. span( ) , "Expected string." ) ,
294
+ }
295
+ }
296
+ attr
297
+ } )
298
+ . last ( ) ,
299
+ impl_attrs,
278
300
}
279
301
}
280
302
281
- fn parse_attr ( attr : & Attribute , mode : GenMode ) -> Option < Meta > {
303
+ fn parse_attr (
304
+ attr : & Attribute ,
305
+ mode : GenMode ,
306
+ globally_called : bool ,
307
+ ) -> ( Option < Meta > , Option < Meta > ) {
282
308
if attr. path ( ) . is_ident ( "getset" ) {
283
309
let meta_list = match attr. parse_args_with ( Punctuated :: < Meta , Token ! [ , ] > :: parse_terminated)
284
310
{
285
311
Ok ( list) => list,
286
312
Err ( e) => abort ! ( attr. span( ) , "Failed to parse getset attribute: {}" , e) ,
287
313
} ;
288
314
289
- let ( last, skip, mut collected) = meta_list
315
+ let ( last, skip, impl_attrs , mut collected) = meta_list
290
316
. into_iter ( )
291
317
. inspect ( |meta| {
292
318
if !( meta. path ( ) . is_ident ( "get" )
@@ -295,21 +321,24 @@ fn parse_attr(attr: &Attribute, mode: GenMode) -> Option<Meta> {
295
321
|| meta. path ( ) . is_ident ( "get_mut" )
296
322
|| meta. path ( ) . is_ident ( "set" )
297
323
|| meta. path ( ) . is_ident ( "set_with" )
298
- || meta. path ( ) . is_ident ( "skip" ) )
324
+ || meta. path ( ) . is_ident ( "skip" )
325
+ || ( meta. path ( ) . is_ident ( "impl_attrs" ) && globally_called) )
299
326
{
300
327
abort ! ( meta. path( ) . span( ) , "unknown setter or getter" )
301
328
}
302
329
} )
303
330
. fold (
304
- ( None , None , Vec :: new ( ) ) ,
305
- |( last, skip, mut collected) , meta| {
331
+ ( None , None , None , Vec :: new ( ) ) ,
332
+ |( last, skip, impl_attrs , mut collected) , meta| {
306
333
if meta. path ( ) . is_ident ( mode. name ( ) ) {
307
- ( Some ( meta) , skip, collected)
334
+ ( Some ( meta) , skip, impl_attrs , collected)
308
335
} else if meta. path ( ) . is_ident ( "skip" ) {
309
- ( last, Some ( meta) , collected)
336
+ ( last, Some ( meta) , impl_attrs, collected)
337
+ } else if meta. path ( ) . is_ident ( "impl_attrs" ) {
338
+ ( last, skip, Some ( meta) , collected)
310
339
} else {
311
340
collected. push ( meta) ;
312
- ( last, skip, collected)
341
+ ( last, skip, impl_attrs , collected)
313
342
}
314
343
} ,
315
344
) ;
@@ -318,26 +347,27 @@ fn parse_attr(attr: &Attribute, mode: GenMode) -> Option<Meta> {
318
347
// Check if there is any setter or getter used with skip, which is
319
348
// forbidden.
320
349
if last. is_none ( ) && collected. is_empty ( ) {
321
- skip
350
+ ( skip, impl_attrs )
322
351
} else {
323
352
abort ! (
324
353
last. or_else( || collected. pop( ) ) . unwrap( ) . path( ) . span( ) ,
325
354
"use of setters and getters with skip is invalid"
326
355
) ;
327
356
}
328
357
} else {
329
- last
358
+ ( last, impl_attrs )
330
359
}
331
360
} else if attr. path ( ) . is_ident ( mode. name ( ) ) {
332
361
// If skip is not used, return the last occurrence of matching
333
362
// setter/getter, if there is any.
334
- attr. meta . clone ( ) . into ( )
363
+ ( attr. meta . clone ( ) . into ( ) , None )
335
364
} else {
336
- None
365
+ ( None , None )
337
366
}
338
367
}
339
368
340
369
fn produce ( ast : & DeriveInput , params : & GenParams ) -> TokenStream2 {
370
+ let impl_attrs = & params. impl_attrs ;
341
371
let name = & ast. ident ;
342
372
let generics = & ast. generics ;
343
373
let ( impl_generics, ty_generics, where_clause) = generics. split_for_impl ( ) ;
@@ -354,6 +384,7 @@ fn produce(ast: &DeriveInput, params: &GenParams) -> TokenStream2 {
354
384
let generated = generate:: implement_for_unnamed ( field, params) ;
355
385
356
386
quote ! {
387
+ #( #impl_attrs) *
357
388
impl #impl_generics #name #ty_generics #where_clause {
358
389
#generated
359
390
}
@@ -362,6 +393,7 @@ fn produce(ast: &DeriveInput, params: &GenParams) -> TokenStream2 {
362
393
let generated = fields. iter ( ) . map ( |f| generate:: implement ( f, params) ) ;
363
394
364
395
quote ! {
396
+ #( #impl_attrs) *
365
397
impl #impl_generics #name #ty_generics #where_clause {
366
398
#( #generated) *
367
399
}
0 commit comments