sittard_macros/
lib.rs

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    // Reject non-async functions
12    let asyncness = input_fn.sig.asyncness.is_some();
13    if !asyncness {
14        // Link the error to the function signature
15        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    // Generate the new function
23    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            // Initialize runtime and block on the async function
32            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}