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 /// - [`Vec<Attribute>`] — parses multiple attributes, including mixed kinds in 57 /// any order 58 /// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation 59 /// `P` with optional trailing punctuation 60 /// - [`Vec<Arm>`] — parses arms separated by optional commas according to the 61 /// same grammar as the inside of a `match` expression 62 /// - [`Vec<Stmt>`] — parses the same as `Block::parse_within` 63 /// - [`Pat`], [`Box<Pat>`] — parses the same as 64 /// `Pat::parse_multi_with_leading_vert` 65 /// - [`Field`] — parses a named or unnamed struct field 66 /// 67 /// [`Vec<Attribute>`]: Attribute 68 /// [`Vec<Arm>`]: Arm 69 /// [`Vec<Stmt>`]: Block::parse_within 70 /// [`Pat`]: Pat::parse_multi_with_leading_vert 71 /// [`Box<Pat>`]: Pat::parse_multi_with_leading_vert 72 /// 73 /// # Panics 74 /// 75 /// Panics if the tokens fail to parse as the expected syntax tree type. The 76 /// caller is responsible for ensuring that the input tokens are syntactically 77 /// valid. 78 #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] 79 #[macro_export] 80 macro_rules! parse_quote { 81 ($($tt:tt)*) => { 82 $crate::__private::parse_quote($crate::__private::quote::quote!($($tt)*)) 83 }; 84 } 85 86 /// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned]. 87 /// 88 /// Please refer to each of their documentation. 89 /// 90 /// # Example 91 /// 92 /// ``` 93 /// use quote::{quote, quote_spanned}; 94 /// use syn::spanned::Spanned; 95 /// use syn::{parse_quote_spanned, ReturnType, Signature}; 96 /// 97 /// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`, 98 /// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`, 99 /// // without introducing any call_site() spans. 100 /// fn make_ret_pinned_future(sig: &mut Signature) { 101 /// let ret = match &sig.output { 102 /// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()), 103 /// ReturnType::Type(_, ret) => quote!(#ret), 104 /// }; 105 /// sig.output = parse_quote_spanned! {ret.span()=> 106 /// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>> 107 /// }; 108 /// } 109 /// ``` 110 #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] 111 #[macro_export] 112 macro_rules! parse_quote_spanned { 113 ($span:expr=> $($tt:tt)*) => { 114 $crate::__private::parse_quote($crate::__private::quote::quote_spanned!($span=> $($tt)*)) 115 }; 116 } 117 118 //////////////////////////////////////////////////////////////////////////////// 119 // Can parse any type that implements Parse. 120 121 use crate::error::Result; 122 use crate::parse::{Parse, ParseStream, Parser}; 123 use proc_macro2::TokenStream; 124 125 // Not public API. 126 #[doc(hidden)] 127 #[track_caller] 128 pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T { 129 let parser = T::parse; 130 match parser.parse2(token_stream) { 131 Ok(t) => t, 132 Err(err) => panic!("{}", err), 133 } 134 } 135 136 #[doc(hidden)] 137 pub trait ParseQuote: Sized { 138 fn parse(input: ParseStream) -> Result<Self>; 139 } 140 141 impl<T: Parse> ParseQuote for T { 142 fn parse(input: ParseStream) -> Result<Self> { 143 <T as Parse>::parse(input) 144 } 145 } 146 147 //////////////////////////////////////////////////////////////////////////////// 148 // Any other types that we want `parse_quote!` to be able to parse. 149 150 use crate::punctuated::Punctuated; 151 #[cfg(any(feature = "full", feature = "derive"))] 152 use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility}; 153 #[cfg(feature = "full")] 154 use crate::{Arm, Block, Pat, Stmt}; 155 156 #[cfg(any(feature = "full", feature = "derive"))] 157 impl ParseQuote for Attribute { 158 fn parse(input: ParseStream) -> Result<Self> { 159 if input.peek(Token![#]) && input.peek2(Token![!]) { 160 attr::parsing::single_parse_inner(input) 161 } else { 162 attr::parsing::single_parse_outer(input) 163 } 164 } 165 } 166 167 #[cfg(any(feature = "full", feature = "derive"))] 168 impl ParseQuote for Vec<Attribute> { 169 fn parse(input: ParseStream) -> Result<Self> { 170 let mut attrs = Vec::new(); 171 while !input.is_empty() { 172 attrs.push(ParseQuote::parse(input)?); 173 } 174 Ok(attrs) 175 } 176 } 177 178 #[cfg(any(feature = "full", feature = "derive"))] 179 impl ParseQuote for Field { 180 fn parse(input: ParseStream) -> Result<Self> { 181 let attrs = input.call(Attribute::parse_outer)?; 182 let vis: Visibility = input.parse()?; 183 184 let ident: Option<Ident>; 185 let colon_token: Option<Token![:]>; 186 let is_named = input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]); 187 if is_named { 188 ident = Some(input.parse()?); 189 colon_token = Some(input.parse()?); 190 } else { 191 ident = None; 192 colon_token = None; 193 } 194 195 let ty: Type = input.parse()?; 196 197 Ok(Field { 198 attrs, 199 vis, 200 mutability: FieldMutability::None, 201 ident, 202 colon_token, 203 ty, 204 }) 205 } 206 } 207 208 #[cfg(feature = "full")] 209 impl ParseQuote for Pat { 210 fn parse(input: ParseStream) -> Result<Self> { 211 Pat::parse_multi_with_leading_vert(input) 212 } 213 } 214 215 #[cfg(feature = "full")] 216 impl ParseQuote for Box<Pat> { 217 fn parse(input: ParseStream) -> Result<Self> { 218 <Pat as ParseQuote>::parse(input).map(Box::new) 219 } 220 } 221 222 impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> { 223 fn parse(input: ParseStream) -> Result<Self> { 224 Self::parse_terminated(input) 225 } 226 } 227 228 #[cfg(feature = "full")] 229 impl ParseQuote for Vec<Stmt> { 230 fn parse(input: ParseStream) -> Result<Self> { 231 Block::parse_within(input) 232 } 233 } 234 235 #[cfg(feature = "full")] 236 impl ParseQuote for Vec<Arm> { 237 fn parse(input: ParseStream) -> Result<Self> { 238 Arm::parse_multiple(input) 239 } 240 } 241