@@ -126,7 +126,7 @@ use self::glob::{glob, Paths};
126126use quote:: quote;
127127use std:: path:: PathBuf ;
128128use syn:: parse:: { Parse , ParseStream , Result } ;
129- use syn:: { parse_macro_input, Expr , ExprLit , Ident , Lit , Token , ItemFn } ;
129+ use syn:: { parse_macro_input, Attribute , Expr , ExprLit , Ident , ItemFn , Lit , Token } ;
130130
131131// Form canonical name without any punctuation/delimiter or special character
132132fn canonical_fn_name ( s : & str ) -> String {
@@ -165,6 +165,13 @@ impl Parse for MacroAttributes {
165165 }
166166}
167167
168+ fn relevant_attribs_from_ast ( func_ast : & ItemFn ) -> Vec < Attribute > {
169+ func_ast. clone ( ) . attrs . into_iter ( ) . filter
170+ ( |a| {
171+ a. path . segments . iter ( ) . all ( |ps| ps. ident !="test_resources" )
172+ } ) . collect ( )
173+ }
174+
168175/// Macro generating test-functions, invoking the fn for each item matching the resource-pattern.
169176///
170177/// The resource-pattern must not expand to empty list, otherwise an error is raised.
@@ -223,7 +230,7 @@ impl Parse for MacroAttributes {
223230/// ```
224231#[ proc_macro_attribute]
225232pub fn test_resources ( attrs : TokenStream , func : TokenStream ) -> TokenStream {
226- let MacroAttributes { glob_pattern } = parse_macro_input ! ( attrs as MacroAttributes ) ;
233+ let MacroAttributes { glob_pattern, } = parse_macro_input ! ( attrs as MacroAttributes ) ;
227234
228235 let pattern = match glob_pattern {
229236 Lit :: Str ( l) => l. value ( ) ,
@@ -241,6 +248,8 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
241248 let func_ast: ItemFn = syn:: parse ( func)
242249 . expect ( "failed to parse tokens as a function" ) ;
243250
251+ let func_attrs = relevant_attribs_from_ast ( & func_ast) ;
252+
244253 let func_ident = func_ast. ident ;
245254
246255 let paths: Paths = glob ( & pattern) . expect ( & format ! ( "No such file or directory {}" , & pattern) ) ;
@@ -261,9 +270,11 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
261270 // quote! requires proc_macro2 elements
262271 let test_ident = proc_macro2:: Ident :: new ( & test_name, proc_macro2:: Span :: call_site ( ) ) ;
263272
273+ let func_attrs = func_attrs. clone ( ) ;
264274 let item = quote ! {
265275 #[ test]
266276 #[ allow( non_snake_case) ]
277+ #( #func_attrs) *
267278 fn # test_ident ( ) {
268279 # func_ident ( #path_as_str . into( ) ) ;
269280 }
@@ -277,6 +288,7 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
277288 if result. 0 == 0 {
278289 panic ! ( "no resource matching the pattern {}" , & pattern) ;
279290 }
291+
280292 // transforming proc_macro2::TokenStream into proc_macro::TokenStream
281293 result. 1 . into ( )
282294}
@@ -360,6 +372,8 @@ pub fn bench_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
360372 let func_ast: ItemFn = syn:: parse ( func)
361373 . expect ( "failed to parse tokens as a function" ) ;
362374
375+ let func_attrs = relevant_attribs_from_ast ( & func_ast) ;
376+
363377 let func_ident = func_ast. ident ;
364378
365379 let paths: Paths = glob ( & pattern) . expect ( & format ! ( "No such file or directory {}" , & pattern) ) ;
@@ -380,9 +394,11 @@ pub fn bench_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
380394 // quote! requires proc_macro2 elements
381395 let test_ident = proc_macro2:: Ident :: new ( & test_name, proc_macro2:: Span :: call_site ( ) ) ;
382396
397+ let func_attrs = func_attrs. clone ( ) ;
383398 let item = quote ! {
384399 #[ bench]
385400 #[ allow( non_snake_case) ]
401+ #( #func_attrs) *
386402 fn # test_ident ( b: & mut test:: Bencher ) {
387403 # func_ident ( b, #path_as_str . into( ) ) ;
388404 }
0 commit comments