Skip to main content

easy_macros_helpers/
parse_macro_input.rs

1#[macro_export]
2/// Adjusted version of syn's `parse_macro_input!` macro for `#[anyhow_result]` procedural macro attribute.
3///
4/// Unlike syn's original `parse_macro_input!` macro, this version returns `Ok(TokenStream)`
5/// on parse errors instead of returning a `TokenStream` directly. This makes
6/// it more suitable for use in procedural macros which are returning `anyhow::Result<TokenStream>`. See `anyhow_result` macro.
7///
8/// # Behavior
9///
10/// On successful parsing, the macro returns the parsed value directly.
11/// On parse errors, it returns `Ok(TokenStream)` containing the error as `compile_error!` tokens,
12/// allowing the error to be displayed at compile time while still providing a valid return value.
13///
14/// # Syntax
15///
16/// ```ignore
17/// // Parse as a specific type
18/// let input = parse_macro_input!(tokens as DeriveInput);
19///
20/// // Parse with a custom parser
21/// let input = parse_macro_input!(tokens with syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated);
22///
23/// // Parse with type inference
24/// let input = parse_macro_input!(tokens);
25/// ```
26///
27/// # Examples
28///
29/// ```ignore
30/// use easy_macros::{parse_macro_input, anyhow_result};
31/// use proc_macro::TokenStream;
32/// use syn::DeriveInput;
33///
34/// #[proc_macro_derive(MyDerive)]
35/// #[anyhow_result]
36/// pub fn my_derive(input: TokenStream) -> anyhow::Result<TokenStream> {
37///     // This will return compile errors automatically on parse failure
38///     let input = parse_macro_input!(input as DeriveInput);
39///     
40///     // Your macro logic here...
41///     Ok(quote::quote! {
42///         // Generated code
43///     }.into())
44/// }
45/// ```
46///
47/// # Advantages over syn's version
48///
49/// - Returns `Ok(TokenStream)` on errors instead of raw `TokenStream`
50/// - Better integration with macros that return for example `anyhow::Result<TokenStream>`
51///
52/// # Parameters
53///
54/// - `$tokenstream` - The input `TokenStream` to parse
55/// - `$ty` - The target type to parse into (with `as` syntax)
56/// - `$parser` - A custom parser function (with `with` syntax)
57macro_rules! parse_macro_input {
58    ($tokenstream:ident as $ty:ty) => {
59        match syn::parse::<$ty>($tokenstream) {
60            syn::__private::Ok(data) => data,
61            syn::__private::Err(err) => {
62                return Ok(syn::__private::TokenStream::from(err.to_compile_error()));
63            }
64        }
65    };
66    ($tokenstream:ident with $parser:path) => {
67        match syn::parse::Parser::parse($parser, $tokenstream) {
68            syn::__private::Ok(data) => data,
69            syn::__private::Err(err) => {
70                return Ok(syn::__private::TokenStream::from(err.to_compile_error()));
71            }
72        }
73    };
74    ($tokenstream:ident) => {
75        $crate::parse_macro_input!($tokenstream as _)
76    };
77}