// SPDX-License-Identifier: Apache-2.0 OR MIT12/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses3/// type inference to figure out a return type for those tokens.4///5/// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html6///7/// The return type can be any syntax tree node that implements the [`Parse`]8/// trait.9///10/// [`Parse`]: crate::parse::Parse11///12/// ```13/// use quote::quote;14/// use syn::{parse_quote, Stmt};15///16/// fn main() {17/// let name = quote!(v);18/// let ty = quote!(u8);19///20/// let stmt: Stmt = parse_quote! {21/// let #name: #ty = Default::default();22/// };23///24/// println!("{:#?}", stmt);25/// }26/// ```27///28/// *This macro is available only if Syn is built with both the `"parsing"` and29/// `"printing"` features.*30///31/// # Example32///33/// The following helper function adds a bound `T: HeapSize` to every type34/// 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/// generics47/// }48/// ```49///50/// # Special cases51///52/// This macro can parse the following additional types as a special case even53/// though they do not implement the `Parse` trait.54///55/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`56/// or inner like `#![...]`57/// - [`Vec<Attribute>`] — parses multiple attributes, including mixed kinds in58/// any order59/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation60/// `P` with optional trailing punctuation61/// - [`Vec<Arm>`] — parses arms separated by optional commas according to the62/// same grammar as the inside of a `match` expression63/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`64/// - [`Pat`], [`Box<Pat>`] — parses the same as65/// `Pat::parse_multi_with_leading_vert`66/// - [`Field`] — parses a named or unnamed struct field67///68/// [`Vec<Attribute>`]: Attribute69/// [`Vec<Arm>`]: Arm70/// [`Vec<Stmt>`]: Block::parse_within71/// [`Pat`]: Pat::parse_multi_with_leading_vert72/// [`Box<Pat>`]: Pat::parse_multi_with_leading_vert73///74/// # Panics75///76/// Panics if the tokens fail to parse as the expected syntax tree type. The77/// caller is responsible for ensuring that the input tokens are syntactically78/// valid.79#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]80#[macro_export]81macro_rules! parse_quote {82($($tt:tt)*) => {83$crate::__private::parse_quote($crate::__private::quote::quote!($($tt)*))84};85}8687/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].88///89/// Please refer to each of their documentation.90///91/// # Example92///93/// ```94/// use quote::{quote, quote_spanned};95/// use syn::spanned::Spanned;96/// use syn::{parse_quote_spanned, ReturnType, Signature};97///98/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,99/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,100/// // without introducing any call_site() spans.101/// fn make_ret_pinned_future(sig: &mut Signature) {102/// let ret = match &sig.output {103/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),104/// ReturnType::Type(_, ret) => quote!(#ret),105/// };106/// sig.output = parse_quote_spanned! {ret.span()=>107/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>108/// };109/// }110/// ```111#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]112#[macro_export]113macro_rules! parse_quote_spanned {114($span:expr=> $($tt:tt)*) => {115$crate::__private::parse_quote($crate::__private::quote::quote_spanned!($span=> $($tt)*))116};117}118119////////////////////////////////////////////////////////////////////////////////120// Can parse any type that implements Parse.121122use crate::error::Result;123use crate::parse::{Parse, ParseStream, Parser};124use proc_macro2::TokenStream;125126// Not public API.127#[doc(hidden)]128#[track_caller]129pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {130let parser = T::parse;131match parser.parse2(token_stream) {132Ok(t) => t,133Err(err) => panic!("{}", err),134}135}136137#[doc(hidden)]138pub trait ParseQuote: Sized {139fn parse(input: ParseStream) -> Result<Self>;140}141142impl<T: Parse> ParseQuote for T {143fn parse(input: ParseStream) -> Result<Self> {144<T as Parse>::parse(input)145}146}147148////////////////////////////////////////////////////////////////////////////////149// Any other types that we want `parse_quote!` to be able to parse.150151use crate::punctuated::Punctuated;152#[cfg(any(feature = "full", feature = "derive"))]153use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility};154#[cfg(feature = "full")]155use crate::{Arm, Block, Pat, Stmt};156157#[cfg(any(feature = "full", feature = "derive"))]158impl ParseQuote for Attribute {159fn parse(input: ParseStream) -> Result<Self> {160if input.peek(Token![#]) && input.peek2(Token![!]) {161attr::parsing::single_parse_inner(input)162} else {163attr::parsing::single_parse_outer(input)164}165}166}167168#[cfg(any(feature = "full", feature = "derive"))]169impl ParseQuote for Vec<Attribute> {170fn parse(input: ParseStream) -> Result<Self> {171let mut attrs = Vec::new();172while !input.is_empty() {173attrs.push(ParseQuote::parse(input)?);174}175Ok(attrs)176}177}178179#[cfg(any(feature = "full", feature = "derive"))]180impl ParseQuote for Field {181fn parse(input: ParseStream) -> Result<Self> {182let attrs = input.call(Attribute::parse_outer)?;183let vis: Visibility = input.parse()?;184185let ident: Option<Ident>;186let colon_token: Option<Token![:]>;187let is_named = input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]);188if is_named {189ident = Some(input.parse()?);190colon_token = Some(input.parse()?);191} else {192ident = None;193colon_token = None;194}195196let ty: Type = input.parse()?;197198Ok(Field {199attrs,200vis,201mutability: FieldMutability::None,202ident,203colon_token,204ty,205})206}207}208209#[cfg(feature = "full")]210impl ParseQuote for Pat {211fn parse(input: ParseStream) -> Result<Self> {212Pat::parse_multi_with_leading_vert(input)213}214}215216#[cfg(feature = "full")]217impl ParseQuote for Box<Pat> {218fn parse(input: ParseStream) -> Result<Self> {219<Pat as ParseQuote>::parse(input).map(Box::new)220}221}222223impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {224fn parse(input: ParseStream) -> Result<Self> {225Self::parse_terminated(input)226}227}228229#[cfg(feature = "full")]230impl ParseQuote for Vec<Stmt> {231fn parse(input: ParseStream) -> Result<Self> {232Block::parse_within(input)233}234}235236#[cfg(feature = "full")]237impl ParseQuote for Vec<Arm> {238fn parse(input: ParseStream) -> Result<Self> {239Arm::parse_multiple(input)240}241}242243244