1use quote::{quote, quote_spanned};
2use syn::spanned::Spanned;
3use syn::{ItemFn, parse_macro_input};
4
5fn test_impl(
6 runtime_path: proc_macro2::TokenStream,
7 item: proc_macro::TokenStream,
8) -> proc_macro::TokenStream {
9 let input_fn = parse_macro_input!(item as ItemFn);
10
11 let asyncness = input_fn.sig.asyncness.is_some();
13 if !asyncness {
14 let sig_span = input_fn.sig.span();
16 let error = quote_spanned! {sig_span=>
17 compile_error!("this attribute can only be used on async functions");
18 };
19 return error.into();
20 }
21
22 let fn_name = &input_fn.sig.ident;
24 let fn_block = &input_fn.block;
25 let vis = &input_fn.vis;
26 let attrs = &input_fn.attrs;
27 let output = quote! {
28 #(#attrs)*
29 #[test]
30 #vis fn #fn_name() {
31 let runtime = #runtime_path;
33 runtime.block_on(async #fn_block)
34 }
35 };
36
37 output.into()
38}
39
40#[proc_macro_attribute]
41pub fn test_priv(
42 _attr: proc_macro::TokenStream,
43 item: proc_macro::TokenStream,
44) -> proc_macro::TokenStream {
45 let runtime_path = quote! { crate::Runtime::default() };
46 test_impl(runtime_path, item)
47}
48
49#[proc_macro_attribute]
50pub fn test(
51 _attr: proc_macro::TokenStream,
52 item: proc_macro::TokenStream,
53) -> proc_macro::TokenStream {
54 let runtime_path = quote! { sittard::Runtime::default() };
55 test_impl(runtime_path, item)
56}