1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{
4 parse_macro_input, punctuated::Punctuated, token::Comma, AttributeArgs, Error, ItemFn,
5 NestedMeta,
6};
7
8#[proc_macro_attribute]
33pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
34 let fn_item = parse_macro_input!(item as ItemFn);
35
36 for attr in &fn_item.attrs {
37 if attr.path.is_ident("test") {
38 return Error::new_spanned(&fn_item, "multiple #[test] attributes were supplied")
39 .to_compile_error()
40 .into();
41 }
42 }
43
44 if fn_item.sig.asyncness.is_none() {
45 return Error::new_spanned(&fn_item, "test fn must be async")
46 .to_compile_error()
47 .into();
48 }
49
50 let p_args = parse_macro_input!(args as AttributeArgs);
51 let attrib: Punctuated<NestedMeta, Comma> = p_args.into_iter().collect();
52
53 let call_by = format_ident!("{}", fn_item.sig.ident);
54
55 quote! (
56 #[::tokio::test(#attrib)]
57 async fn #call_by() {
58 #fn_item
59
60 ::near_prop::prop_test(#call_by as fn(PropContext, _) -> _).await
61 }
62 )
63 .into()
64}