@@ -174,13 +174,29 @@ fn parse_bool(bool: syn::Lit, span: Span, field: &str) -> Result<bool, syn::Erro
174
174
}
175
175
176
176
fn parse_knobs (
177
- mut input : syn :: ItemFn ,
177
+ input_tokens : TokenStream ,
178
178
args : syn:: AttributeArgs ,
179
179
is_test : bool ,
180
180
rt_multi_thread : bool ,
181
181
) -> Result < TokenStream , syn:: Error > {
182
+ let mut input: syn:: ItemFn = syn:: parse ( input_tokens. clone ( ) ) ?;
183
+
184
+ if ( is_test || input. sig . ident == "main" ) && !input. sig . inputs . is_empty ( ) {
185
+ let function = if is_test { "test" } else { "main" } ;
186
+
187
+ return Err ( syn:: Error :: new_spanned (
188
+ & input. sig . inputs ,
189
+ format_args ! ( "the {} function cannot accept arguments" , function) ,
190
+ ) ) ;
191
+ }
192
+ if is_test {
193
+ if let Some ( attr) = input. attrs . iter ( ) . find ( |attr| attr. path . is_ident ( "test" ) ) {
194
+ let msg = "second test attribute is supplied" ;
195
+ return Err ( syn:: Error :: new_spanned ( attr, msg) ) ;
196
+ }
197
+ }
198
+
182
199
let sig = & mut input. sig ;
183
- let body = & input. block ;
184
200
let attrs = & input. attrs ;
185
201
let vis = input. vis ;
186
202
@@ -291,6 +307,12 @@ fn parse_knobs(
291
307
}
292
308
} ;
293
309
310
+ // The last token of a function item is always its body. We use the input token stream directly
311
+ // instead of printing the parsed function to make sure that Rust preserves None-delimited
312
+ // groups inside the function body; see <https://github.com/tokio-rs/tokio/issues/3579>.
313
+ let body =
314
+ proc_macro2:: TokenStream :: from ( TokenStream :: from ( input_tokens. into_iter ( ) . last ( ) . unwrap ( ) ) ) ;
315
+
294
316
let result = quote ! {
295
317
#header
296
318
#( #attrs) *
@@ -308,38 +330,11 @@ fn parse_knobs(
308
330
309
331
#[ cfg( not( test) ) ] // Work around for rust-lang/rust#62127
310
332
pub ( crate ) fn main ( args : TokenStream , item : TokenStream , rt_multi_thread : bool ) -> TokenStream {
311
- let input = syn:: parse_macro_input!( item as syn:: ItemFn ) ;
312
333
let args = syn:: parse_macro_input!( args as syn:: AttributeArgs ) ;
313
-
314
- if input. sig . ident == "main" && !input. sig . inputs . is_empty ( ) {
315
- let msg = "the main function cannot accept arguments" ;
316
- return syn:: Error :: new_spanned ( & input. sig . ident , msg)
317
- . to_compile_error ( )
318
- . into ( ) ;
319
- }
320
-
321
- parse_knobs ( input, args, false , rt_multi_thread) . unwrap_or_else ( |e| e. to_compile_error ( ) . into ( ) )
334
+ parse_knobs ( item, args, false , rt_multi_thread) . unwrap_or_else ( |e| e. to_compile_error ( ) . into ( ) )
322
335
}
323
336
324
337
pub ( crate ) fn test ( args : TokenStream , item : TokenStream , rt_multi_thread : bool ) -> TokenStream {
325
- let input = syn:: parse_macro_input!( item as syn:: ItemFn ) ;
326
338
let args = syn:: parse_macro_input!( args as syn:: AttributeArgs ) ;
327
-
328
- for attr in & input. attrs {
329
- if attr. path . is_ident ( "test" ) {
330
- let msg = "second test attribute is supplied" ;
331
- return syn:: Error :: new_spanned ( & attr, msg)
332
- . to_compile_error ( )
333
- . into ( ) ;
334
- }
335
- }
336
-
337
- if !input. sig . inputs . is_empty ( ) {
338
- let msg = "the test function cannot accept arguments" ;
339
- return syn:: Error :: new_spanned ( & input. sig . inputs , msg)
340
- . to_compile_error ( )
341
- . into ( ) ;
342
- }
343
-
344
- parse_knobs ( input, args, true , rt_multi_thread) . unwrap_or_else ( |e| e. to_compile_error ( ) . into ( ) )
339
+ parse_knobs ( item, args, true , rt_multi_thread) . unwrap_or_else ( |e| e. to_compile_error ( ) . into ( ) )
345
340
}
0 commit comments