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