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}