asmov_common_testing_macro/
lib.rs

1use proc_macro;
2use proc_macro2;
3use quote::quote;
4use syn;
5
6#[proc_macro_attribute]
7pub fn tested(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
8    match parse_tested_macro(proc_macro2::TokenStream::from(attr), proc_macro2::TokenStream::from(item)) {
9        Ok(token_stream) => proc_macro::TokenStream::from(token_stream),
10        Err(err) => proc_macro::TokenStream::from(err.to_compile_error())
11    }
12}
13
14fn parse_tested_macro(_attr: proc_macro2::TokenStream, item: proc_macro2::TokenStream) -> syn::Result<proc_macro2::TokenStream> {
15    let item: syn::ItemFn = syn::parse2(item)?;
16
17    // append a #[test] if there isn't one
18    let test_attr = if let Some(_)= item.attrs.iter().find(|attr| attr.path().is_ident("test")) {
19        quote!{}
20    } else {
21        quote!{ #[test] }
22    };
23
24    // append a #[named] if there isn't one
25    let named_attr = if let Some(_)= item.attrs.iter().find(|attr| attr.path().is_ident("named")) {
26        quote!{}
27    } else {
28        quote!{ #[named] }
29    };
30
31    let output = quote! {
32        #named_attr
33        #test_attr
34        #item
35    };
36
37    Ok(output)
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_attr() {
46        let test_one_attr = quote::quote!{
47            #[tested]
48        };
49
50        let test_one_item = quote::quote!{
51            fn test_one() {}
52        };
53
54        parse_tested_macro(test_one_attr, test_one_item).unwrap();
55    }
56}