1/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
2/// type inference to figure out a return type for those tokens.
3///
4/// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html
5///
6/// The return type can be any syntax tree node that implements the [`Parse`]
7/// trait.
8///
9/// [`Parse`]: crate::parse::Parse
10///
11/// ```
12/// use quote::quote;
13/// use syn::{parse_quote, Stmt};
14///
15/// fn main() {
16/// let name = quote!(v);
17/// let ty = quote!(u8);
18///
19/// let stmt: Stmt = parse_quote! {
20/// let #name: #ty = Default::default();
21/// };
22///
23/// println!("{:#?}", stmt);
24/// }
25/// ```
26///
27/// *This macro is available only if Syn is built with both the `"parsing"` and
28/// `"printing"` features.*
29///
30/// # Example
31///
32/// The following helper function adds a bound `T: HeapSize` to every type
33/// parameter `T` in the input generics.
34///
35/// ```
36/// use syn::{parse_quote, Generics, GenericParam};
37///
38/// // Add a bound `T: HeapSize` to every type parameter T.
39/// fn add_trait_bounds(mut generics: Generics) -> Generics {
40/// for param in &mut generics.params {
41/// if let GenericParam::Type(type_param) = param {
42/// type_param.bounds.push(parse_quote!(HeapSize));
43/// }
44/// }
45/// generics
46/// }
47/// ```
48///
49/// # Special cases
50///
51/// This macro can parse the following additional types as a special case even
52/// though they do not implement the `Parse` trait.
53///
54/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
55/// or inner like `#![...]`
56/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
57/// `P` with optional trailing punctuation
58/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
59///
60/// [`Vec<Stmt>`]: Block::parse_within
61///
62/// # Panics
63///
64/// Panics if the tokens fail to parse as the expected syntax tree type. The
65/// caller is responsible for ensuring that the input tokens are syntactically
66/// valid.
67#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
68#[macro_export]
69macro_rules! parse_quote {
70 ($($tt:tt)*) => {
71 $crate::__private::parse_quote($crate::__private::quote::quote!($($tt)*))
72 };
73}
74
75/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
76///
77/// Please refer to each of their documentation.
78///
79/// # Example
80///
81/// ```
82/// use quote::{quote, quote_spanned};
83/// use syn::spanned::Spanned;
84/// use syn::{parse_quote_spanned, ReturnType, Signature};
85///
86/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
87/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
88/// // without introducing any call_site() spans.
89/// fn make_ret_pinned_future(sig: &mut Signature) {
90/// let ret = match &sig.output {
91/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
92/// ReturnType::Type(_, ret) => quote!(#ret),
93/// };
94/// sig.output = parse_quote_spanned! {ret.span()=>
95/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
96/// };
97/// }
98/// ```
99#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
100#[macro_export]
101macro_rules! parse_quote_spanned {
102 ($span:expr=> $($tt:tt)*) => {
103 $crate::__private::parse_quote($crate::__private::quote::quote_spanned!($span=> $($tt)*))
104 };
105}
106
107////////////////////////////////////////////////////////////////////////////////
108// Can parse any type that implements Parse.
109
110use crate::error::Result;
111use crate::parse::{Parse, ParseStream, Parser};
112use proc_macro2::TokenStream;
113
114// Not public API.
115#[doc(hidden)]
116pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
117 let parser: fn parse(&ParseBuffer<'_>) -> … = T::parse;
118 match parser.parse2(tokens:token_stream) {
119 Ok(t: T) => t,
120 Err(err: Error) => panic!("{}", err),
121 }
122}
123
124#[doc(hidden)]
125pub trait ParseQuote: Sized {
126 fn parse(input: ParseStream) -> Result<Self>;
127}
128
129impl<T: Parse> ParseQuote for T {
130 fn parse(input: ParseStream) -> Result<Self> {
131 <T as Parse>::parse(input)
132 }
133}
134
135////////////////////////////////////////////////////////////////////////////////
136// Any other types that we want `parse_quote!` to be able to parse.
137
138use crate::punctuated::Punctuated;
139#[cfg(any(feature = "full", feature = "derive"))]
140use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility};
141#[cfg(feature = "full")]
142use crate::{Block, Pat, Stmt};
143
144#[cfg(any(feature = "full", feature = "derive"))]
145impl ParseQuote for Attribute {
146 fn parse(input: ParseStream) -> Result<Self> {
147 if input.peek(Token![#]) && input.peek2(Token![!]) {
148 attr::parsing::single_parse_inner(input)
149 } else {
150 attr::parsing::single_parse_outer(input)
151 }
152 }
153}
154
155#[cfg(any(feature = "full", feature = "derive"))]
156impl ParseQuote for Field {
157 fn parse(input: ParseStream) -> Result<Self> {
158 let attrs = input.call(Attribute::parse_outer)?;
159 let vis: Visibility = input.parse()?;
160
161 let ident: Option<Ident>;
162 let colon_token: Option<Token![:]>;
163 let is_named = input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]);
164 if is_named {
165 ident = Some(input.parse()?);
166 colon_token = Some(input.parse()?);
167 } else {
168 ident = None;
169 colon_token = None;
170 }
171
172 let ty: Type = input.parse()?;
173
174 Ok(Field {
175 attrs,
176 vis,
177 mutability: FieldMutability::None,
178 ident,
179 colon_token,
180 ty,
181 })
182 }
183}
184
185#[cfg(feature = "full")]
186impl ParseQuote for Pat {
187 fn parse(input: ParseStream) -> Result<Self> {
188 Pat::parse_multi_with_leading_vert(input)
189 }
190}
191
192#[cfg(feature = "full")]
193impl ParseQuote for Box<Pat> {
194 fn parse(input: ParseStream) -> Result<Self> {
195 <Pat as ParseQuote>::parse(input).map(op:Box::new)
196 }
197}
198
199impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
200 fn parse(input: ParseStream) -> Result<Self> {
201 Self::parse_terminated(input)
202 }
203}
204
205#[cfg(feature = "full")]
206impl ParseQuote for Vec<Stmt> {
207 fn parse(input: ParseStream) -> Result<Self> {
208 Block::parse_within(input)
209 }
210}
211