]> git.proxmox.com Git - cargo.git/blob - vendor/syn/src/parse_macro_input.rs
New upstream version 0.47.0
[cargo.git] / vendor / syn / src / 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 ///
47 /// <br>
48 ///
49 /// # Usage with Parser
50 ///
51 /// This macro can also be used with the [`Parser` trait] for types that have
52 /// multiple ways that they can be parsed.
53 ///
54 /// [`Parser` trait]: crate::rustdoc_workaround::parse_module::Parser
55 ///
56 /// ```
57 /// # extern crate proc_macro;
58 /// #
59 /// # use proc_macro::TokenStream;
60 /// # use syn::{parse_macro_input, Result};
61 /// # use syn::parse::ParseStream;
62 /// #
63 /// # struct MyMacroInput {}
64 /// #
65 /// impl MyMacroInput {
66 /// fn parse_alternate(input: ParseStream) -> Result<Self> {
67 /// /* ... */
68 /// # Ok(MyMacroInput {})
69 /// }
70 /// }
71 ///
72 /// # const IGNORE: &str = stringify! {
73 /// #[proc_macro]
74 /// # };
75 /// pub fn my_macro(tokens: TokenStream) -> TokenStream {
76 /// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
77 ///
78 /// /* ... */
79 /// # "".parse().unwrap()
80 /// }
81 /// ```
82 ///
83 /// <br>
84 ///
85 /// # Expansion
86 ///
87 /// `parse_macro_input!($variable as $Type)` expands to something like:
88 ///
89 /// ```no_run
90 /// # extern crate proc_macro;
91 /// #
92 /// # macro_rules! doc_test {
93 /// # ($variable:ident as $Type:ty) => {
94 /// match syn::parse::<$Type>($variable) {
95 /// Ok(syntax_tree) => syntax_tree,
96 /// Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
97 /// }
98 /// # };
99 /// # }
100 /// #
101 /// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
102 /// # let _ = doc_test!(input as syn::Ident);
103 /// # proc_macro::TokenStream::new()
104 /// # }
105 /// ```
106 #[macro_export]
107 macro_rules! parse_macro_input {
108 ($tokenstream:ident as $ty:ty) => {
109 match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
110 $crate::export::Ok(data) => data,
111 $crate::export::Err(err) => {
112 return $crate::export::TokenStream::from(err.to_compile_error());
113 }
114 }
115 };
116 ($tokenstream:ident with $parser:path) => {
117 match $crate::parse::Parser::parse($parser, $tokenstream) {
118 $crate::export::Ok(data) => data,
119 $crate::export::Err(err) => {
120 return $crate::export::TokenStream::from(err.to_compile_error());
121 }
122 }
123 };
124 ($tokenstream:ident) => {
125 $crate::parse_macro_input!($tokenstream as _)
126 };
127 }
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // Can parse any type that implements Parse.
131
132 use crate::parse::{Parse, ParseStream, Parser, Result};
133 use proc_macro::TokenStream;
134
135 // Not public API.
136 #[doc(hidden)]
137 pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
138 T::parse.parse(token_stream)
139 }
140
141 // Not public API.
142 #[doc(hidden)]
143 pub trait ParseMacroInput: Sized {
144 fn parse(input: ParseStream) -> Result<Self>;
145 }
146
147 impl<T: Parse> ParseMacroInput for T {
148 fn parse(input: ParseStream) -> Result<Self> {
149 <T as Parse>::parse(input)
150 }
151 }
152
153 ////////////////////////////////////////////////////////////////////////////////
154 // Any other types that we want `parse_macro_input!` to be able to parse.
155
156 #[cfg(any(feature = "full", feature = "derive"))]
157 use crate::AttributeArgs;
158
159 #[cfg(any(feature = "full", feature = "derive"))]
160 impl ParseMacroInput for AttributeArgs {
161 fn parse(input: ParseStream) -> Result<Self> {
162 let mut metas = Vec::new();
163
164 loop {
165 if input.is_empty() {
166 break;
167 }
168 let value = input.parse()?;
169 metas.push(value);
170 if input.is_empty() {
171 break;
172 }
173 input.parse::<Token![,]>()?;
174 }
175
176 Ok(metas)
177 }
178 }