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}