rsmack_utils/
exec.rs

1#![allow(clippy::crate_in_macro_def)]
2//! Macro utils to call a given **proc-macro** implementation with attrs & item parsing boilerplate handled with [darling]
3
4/// Use [`call_attr_proc_macro`] on `impls` mod with `Args` args ident
5#[macro_export]
6macro_rules! call_attr_impls_with_args {
7    (
8            $exec_fn_mod_ident:ident,
9            $item_ty:ty,
10            $attr_tok_stream:ident,
11            $item_tok_stream:ident
12        ) => {
13        rsmack_utils::exec::call_attr_proc_macro!(
14            impls,
15            Args,
16            $exec_fn_mod_ident,
17            $item_ty,
18            $attr_tok_stream,
19            $item_tok_stream
20        )
21    };
22}
23/// Build an [`ExecEnv`](crate::megamac::ExecEnv)
24#[macro_export]
25macro_rules! build_env {
26    (
27        $implementations_mod_ident:ident,
28        $exec_args_ident:ident,
29        $exec_fn_mod_ident:ident
30    ) => {{
31        // This can not be put in the builder otherwise the path is not the caller one
32        let module_path = std::module_path!();
33        rsmack_utils::megamac::ExecEnv::builder(
34            module_path,
35            stringify!($implementations_mod_ident),
36            stringify!($exec_args_ident),
37            stringify!($exec_fn_mod_ident),
38        )
39        .build()
40    }};
41}
42/// Call an attribute proc-macro implementation function named `exec`.
43///
44/// This macro is **proc-macro only**.
45/// Call a proc-macro implementation function named `exec`,
46/// located in the given `implementations module ident`,
47/// with the given `args type ident` and `type of the item` for [`syn::parse_macro_input`]
48#[macro_export]
49macro_rules! call_attr_proc_macro {
50    (
51        $implementations_mod_ident:ident,
52        $exec_args_ident:ident,
53        $exec_fn_mod_ident:ident,
54        $item_ty:ty,
55        $attr_tok_stream:ident,
56        $item_tok_stream:ident
57    ) => {{
58        use darling::*;
59
60        let meta_list = match ast::NestedMeta::parse_meta_list($attr_tok_stream.into()) {
61            Ok(v) => v,
62            Err(e) => {
63                return proc_macro::TokenStream::from(Error::from(e).write_errors());
64            }
65        };
66        let parsed_item = syn::parse_macro_input!($item_tok_stream as $item_ty);
67        let parsed_args =
68            match crate::$implementations_mod_ident::$exec_fn_mod_ident::$exec_args_ident::from_list(
69                &meta_list,
70            ) {
71                Ok(v) => v,
72                Err(e) => {
73                    return proc_macro::TokenStream::from(e.write_errors());
74                }
75            };
76        let env = rsmack_utils::build_env!($implementations_mod_ident, $exec_args_ident, $exec_fn_mod_ident);
77
78        crate::$implementations_mod_ident::$exec_fn_mod_ident::exec(
79            parsed_args,
80            parsed_item,
81            env
82        )
83        .into()
84    }};
85}
86/// Use [`call_func_proc_macro`] on `impls` mod with `Args` args ident
87#[macro_export]
88macro_rules! call_func_impls_with_args {
89    (
90            $exec_fn_mod_ident:ident,
91            $args_tok_stream:ident
92        ) => {
93        rsmack_utils::exec::call_func_proc_macro!(impls, Args, $exec_fn_mod_ident, $args_tok_stream)
94    };
95}
96/// Use [`call_derive_proc_macro`] on `impls` mod with `Args` args ident
97#[macro_export]
98macro_rules! call_derive_impls_with_args {
99    (
100            $exec_fn_mod_ident:ident,
101            $item_tok_stream:ident
102        ) => {
103        rsmack_utils::exec::call_derive_proc_macro!(
104            impls,
105            Args,
106            $exec_fn_mod_ident,
107            $item_tok_stream
108        )
109    };
110}
111/// Call a function proc-macro implementation function named `exec`.
112#[macro_export]
113macro_rules! call_func_proc_macro {
114    (
115        $implementations_mod_ident:ident,
116        $exec_args_ident:ident,
117        $exec_fn_mod_ident:ident,
118        $args_tok_stream:ident
119    ) => {{
120        use darling::*;
121
122        let meta_list = match ast::NestedMeta::parse_meta_list($args_tok_stream.into()) {
123            Ok(v) => v,
124            Err(e) => {
125                return proc_macro::TokenStream::from(Error::from(e).write_errors());
126            }
127        };
128        let parsed_args =
129            match crate::$implementations_mod_ident::$exec_fn_mod_ident::$exec_args_ident::from_list(
130                &meta_list,
131            ) {
132                Ok(v) => v,
133                Err(e) => {
134                    return proc_macro::TokenStream::from(e.write_errors());
135                }
136            };
137        let env = rsmack_utils::build_env!($implementations_mod_ident, $exec_args_ident, $exec_fn_mod_ident);
138
139        crate::$implementations_mod_ident::$exec_fn_mod_ident::exec(
140            parsed_args,
141            env
142        )
143        .into()
144    }};
145}
146
147/// Call a derive proc-macro implementation function named `exec`.
148#[macro_export]
149macro_rules! call_derive_proc_macro {
150    (
151        $implementations_mod_ident:ident,
152        $exec_args_ident:ident,
153        $exec_fn_mod_ident:ident,
154        $item_tok_stream:ident
155    ) => {{
156        use darling::*;
157        let parsed_item = syn::parse_macro_input!($item_tok_stream as syn::DeriveInput);
158        let env = rsmack_utils::build_env!(
159            $implementations_mod_ident,
160            $exec_args_ident,
161            $exec_fn_mod_ident
162        );
163        crate::$implementations_mod_ident::$exec_fn_mod_ident::exec(parsed_item, env).into()
164    }};
165}
166
167pub use call_attr_impls_with_args;
168pub use call_attr_proc_macro;
169pub use call_derive_impls_with_args;
170pub use call_derive_proc_macro;
171pub use call_func_impls_with_args;
172pub use call_func_proc_macro;