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 the `"parsing"` feature,
28/// although interpolation of syntax tree nodes into the quoted tokens is only
29/// supported if Syn is built with the `"printing"` feature as well.*
30///
31/// # Example
32///
33/// The following helper function adds a bound `T: HeapSize` to every type
34/// parameter `T` in the input generics.
35///
36/// ```
37/// use syn::{parse_quote, Generics, GenericParam};
38///
39/// // Add a bound `T: HeapSize` to every type parameter T.
40/// fn add_trait_bounds(mut generics: Generics) -> Generics {
41/// for param in &mut generics.params {
42/// if let GenericParam::Type(type_param) = param {
43/// type_param.bounds.push(parse_quote!(HeapSize));
44/// }
45/// }
46/// generics
47/// }
48/// ```
49///
50/// # Special cases
51///
52/// This macro can parse the following additional types as a special case even
53/// though they do not implement the `Parse` trait.
54///
55/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
56/// or inner like `#![...]`
57/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
58/// `P` with optional trailing punctuation
59/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
60///
61/// [`Vec<Stmt>`]: Block::parse_within
62///
63/// # Panics
64///
65/// Panics if the tokens fail to parse as the expected syntax tree type. The
66/// caller is responsible for ensuring that the input tokens are syntactically
67/// valid.
68#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
69#[macro_export]
70macro_rules! parse_quote {
71 ($($tt:tt)*) => {
72 $crate::parse_quote::parse($crate::__private::quote::quote!($($tt)*))
73 };
74}
75
76/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
77///
78/// Please refer to each of their documentation.
79///
80/// # Example
81///
82/// ```
83/// use quote::{quote, quote_spanned};
84/// use syn::spanned::Spanned;
85/// use syn::{parse_quote_spanned, ReturnType, Signature};
86///
87/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
88/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
89/// // without introducing any call_site() spans.
90/// fn make_ret_pinned_future(sig: &mut Signature) {
91/// let ret = match &sig.output {
92/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
93/// ReturnType::Type(_, ret) => quote!(#ret),
94/// };
95/// sig.output = parse_quote_spanned! {ret.span()=>
96/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
97/// };
98/// }
99/// ```
100#[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
101#[macro_export]
102macro_rules! parse_quote_spanned {
103 ($span:expr=> $($tt:tt)*) => {
104 $crate::parse_quote::parse($crate::__private::quote::quote_spanned!($span=> $($tt)*))
105 };
106}
107
108////////////////////////////////////////////////////////////////////////////////
109// Can parse any type that implements Parse.
110
111use crate::parse::{Parse, ParseStream, Parser, Result};
112use proc_macro2::TokenStream;
113
114// Not public API.
115#[doc(hidden)]
116pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
117 let parser = T::parse;
118 match parser.parse2(token_stream) {
119 Ok(t) => t,
120 Err(err) => panic!("{}", err),
121 }
122}
123
124// Not public API.
125#[doc(hidden)]
126pub trait ParseQuote: Sized {
127 fn parse(input: ParseStream) -> Result<Self>;
128}
129
130impl<T: Parse> ParseQuote for T {
131 fn parse(input: ParseStream) -> Result<Self> {
132 <T as Parse>::parse(input)
133 }
134}
135
136////////////////////////////////////////////////////////////////////////////////
137// Any other types that we want `parse_quote!` to be able to parse.
138
139use crate::punctuated::Punctuated;
140#[cfg(any(feature = "full", feature = "derive"))]
141use crate::{attr, Attribute};
142#[cfg(feature = "full")]
143use crate::{Block, Stmt};
144
145#[cfg(any(feature = "full", feature = "derive"))]
146impl ParseQuote for Attribute {
147 fn parse(input: ParseStream) -> Result<Self> {
148 if input.peek(Token![#]) && input.peek2(Token![!]) {
149 attr::parsing::single_parse_inner(input)
150 } else {
151 attr::parsing::single_parse_outer(input)
152 }
153 }
154}
155
156impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
157 fn parse(input: ParseStream) -> Result<Self> {
158 Self::parse_terminated(input)
159 }
160}
161
162#[cfg(feature = "full")]
163impl ParseQuote for Vec<Stmt> {
164 fn parse(input: ParseStream) -> Result<Self> {
165 Block::parse_within(input)
166 }
167}
168