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