mry_macros/
lib.rs

1mod attrs;
2mod create_behaviors;
3mod create_matchers;
4mod item_fn;
5mod item_impl;
6mod item_struct;
7mod item_trait;
8mod lock;
9mod method;
10mod new;
11use attrs::MryAttr;
12use darling::ast::NestedMeta;
13use darling::FromMeta;
14use lock::LockPaths;
15use proc_macro2::TokenStream;
16use quote::ToTokens;
17use syn::visit_mut::VisitMut;
18use syn::{parse, parse2, parse_macro_input, ExprStruct, ItemFn, ItemImpl, ItemStruct, ItemTrait};
19
20/// functions may not be instrumented if they take more than this number of arguments
21const MAX_ARGUMENT_COUNT: u32 = 10;
22
23enum TargetItem {
24    Struct(ItemStruct),
25    Impl(ItemImpl),
26    Trait(ItemTrait),
27    Fn(ItemFn),
28}
29
30#[proc_macro_attribute]
31pub fn mry(
32    attr: proc_macro::TokenStream,
33    input: proc_macro::TokenStream,
34) -> proc_macro::TokenStream {
35    let attr = MryAttr::from_list(&NestedMeta::parse_meta_list(attr.into()).unwrap()).unwrap();
36    match parse(input.clone())
37        .map(TargetItem::Struct)
38        .or_else(|_| parse(input.clone()).map(TargetItem::Impl))
39        .or_else(|_| parse(input.clone()).map(TargetItem::Trait))
40        .or_else(|_| parse(input.clone()).map(TargetItem::Fn))
41    {
42        Ok(target) => {
43            let token_stream = match target {
44                TargetItem::Struct(target) => item_struct::transform(target),
45                TargetItem::Impl(target) => item_impl::transform(&attr, target),
46                TargetItem::Trait(target) => item_trait::transform(&attr, target),
47                TargetItem::Fn(target) => item_fn::transform(&attr, target),
48            };
49            if attr.debug.is_present() {
50                println!("{token_stream}");
51            }
52            token_stream.into()
53        }
54        Err(err) => err.to_compile_error().into(),
55    }
56}
57
58#[proc_macro]
59pub fn new(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
60    new::transform(parse_macro_input!(input as ExprStruct)).into()
61}
62
63#[proc_macro]
64pub fn create_behaviors(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
65    create_behaviors::create().into()
66}
67
68#[proc_macro]
69pub fn create_matchers(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
70    create_matchers::create().into()
71}
72
73#[proc_macro_attribute]
74pub fn lock(
75    attribute: proc_macro::TokenStream,
76    input: proc_macro::TokenStream,
77) -> proc_macro::TokenStream {
78    lock::transform(
79        parse_macro_input!(attribute as LockPaths),
80        parse_macro_input!(input as ItemFn),
81    )
82    .into()
83}
84
85struct M {
86    mry_attr: MryAttr,
87    tokens: TokenStream,
88}
89
90impl VisitMut for M {
91    fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
92        item_trait::transform(&self.mry_attr, i.clone()).to_tokens(&mut self.tokens)
93    }
94    fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
95        item_struct::transform(i.clone()).to_tokens(&mut self.tokens)
96    }
97    fn visit_item_impl_mut(&mut self, i: &mut ItemImpl) {
98        item_impl::transform(&self.mry_attr, i.clone()).to_tokens(&mut self.tokens)
99    }
100}
101
102#[proc_macro]
103pub fn m(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
104    let mut m = M {
105        mry_attr: MryAttr::default(),
106        tokens: TokenStream::default(),
107    };
108    m.visit_file_mut(&mut parse2(input.into()).unwrap());
109    m.tokens.into()
110}