syn/
parse_macro_input.rs

1/// Parse the input TokenStream of a macro, triggering a compile error if the
2/// tokens fail to parse.
3///
4/// Refer to the [`parse` module] documentation for more details about parsing
5/// in Syn.
6///
7/// [`parse` module]: crate::rustdoc_workaround::parse_module
8///
9/// <br>
10///
11/// # Intended usage
12///
13/// This macro must be called from a function that returns
14/// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
15/// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
16/// #\[proc_macro_attribute\] attribute.
17///
18/// ```
19/// extern crate proc_macro;
20///
21/// use proc_macro::TokenStream;
22/// use syn::{parse_macro_input, Result};
23/// use syn::parse::{Parse, ParseStream};
24///
25/// struct MyMacroInput {
26///     /* ... */
27/// }
28///
29/// impl Parse for MyMacroInput {
30///     fn parse(input: ParseStream) -> Result<Self> {
31///         /* ... */
32/// #       Ok(MyMacroInput {})
33///     }
34/// }
35///
36/// # const IGNORE: &str = stringify! {
37/// #[proc_macro]
38/// # };
39/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
40///     let input = parse_macro_input!(tokens as MyMacroInput);
41///
42///     /* ... */
43/// #   "".parse().unwrap()
44/// }
45/// ```
46#[macro_export(local_inner_macros)]
47macro_rules! parse_macro_input {
48    ($tokenstream:ident as $ty:ty) => {
49        match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
50            $crate::export::Ok(data) => data,
51            $crate::export::Err(err) => {
52                return $crate::export::TokenStream::from(err.to_compile_error());
53            }
54        }
55    };
56    ($tokenstream:ident) => {
57        parse_macro_input!($tokenstream as _)
58    };
59}
60
61////////////////////////////////////////////////////////////////////////////////
62// Can parse any type that implements Parse.
63
64use crate::parse::{Parse, ParseStream, Parser, Result};
65use proc_macro::TokenStream;
66
67// Not public API.
68#[doc(hidden)]
69pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
70    T::parse.parse(token_stream)
71}
72
73// Not public API.
74#[doc(hidden)]
75pub trait ParseMacroInput: Sized {
76    fn parse(input: ParseStream) -> Result<Self>;
77}
78
79impl<T: Parse> ParseMacroInput for T {
80    fn parse(input: ParseStream) -> Result<Self> {
81        <T as Parse>::parse(input)
82    }
83}
84
85////////////////////////////////////////////////////////////////////////////////
86// Any other types that we want `parse_macro_input!` to be able to parse.
87
88#[cfg(any(feature = "full", feature = "derive"))]
89use crate::AttributeArgs;
90
91#[cfg(any(feature = "full", feature = "derive"))]
92impl ParseMacroInput for AttributeArgs {
93    fn parse(input: ParseStream) -> Result<Self> {
94        let mut metas = Vec::new();
95
96        loop {
97            if input.is_empty() {
98                break;
99            }
100            let value = input.parse()?;
101            metas.push(value);
102            if input.is_empty() {
103                break;
104            }
105            input.parse::<Token![,]>()?;
106        }
107
108        Ok(metas)
109    }
110}