satchel-macro 0.1.0

Procedural macros for satchel, enabling ergonomic test registration and discovery.
Documentation
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse_macro_input, ItemFn};

#[proc_macro_attribute]
pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
    expand_test_or_bench(item, quote! {::satchel::TestKind::Unit }, "__SATCHEL_TEST_")
}

#[proc_macro_attribute]
pub fn bench(_attr: TokenStream, item: TokenStream) -> TokenStream {
    expand_test_or_bench(
        item,
        quote! { ::satchel::TestKind::Benchmark },
        "__SATCHEL_BENCH_",
    )
}

fn expand_test_or_bench(
    input: TokenStream,
    kind: quote::__private::TokenStream,
    prefix: &str,
) -> TokenStream {
    let input_fn = parse_macro_input!(input as ItemFn);
    let fn_name = &input_fn.sig.ident;
    let fn_name_str = fn_name.to_string();
    let static_name = format_ident!("{}{}", prefix, fn_name_str.to_uppercase());

    let expanded = quote! {
        #[linkme::distributed_slice(::satchel::test_harness::TESTS)]
        static #static_name: ::satchel::test_harness::TestCase = ::satchel::test_harness::TestCase {
            name: #fn_name_str,
            module_path: ::std::module_path!(),
            kind: #kind,
            test_fn: #fn_name,
        };

        #input_fn
    };

    TokenStream::from(expanded)
}