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.
4 /// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html
6 /// The return type can be any syntax tree node that implements the [`Parse`]
9 /// [`Parse`]: crate::parse::Parse
13 /// use syn::{parse_quote, Stmt};
16 /// let name = quote!(v);
17 /// let ty = quote!(u8);
19 /// let stmt: Stmt = parse_quote! {
20 /// let #name: #ty = Default::default();
23 /// println!("{:#?}", stmt);
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.*
33 /// The following helper function adds a bound `T: HeapSize` to every type
34 /// parameter `T` in the input generics.
37 /// use syn::{parse_quote, Generics, GenericParam};
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));
52 /// This macro can parse the following additional types as a special case even
53 /// though they do not implement the `Parse` trait.
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`
61 /// [`Punctuated<T, P>`]: crate::punctuated::Punctuated
62 /// [`Vec<Stmt>`]: Block::parse_within
66 /// Panics if the tokens fail to parse as the expected syntax tree type. The
67 /// caller is responsible for ensuring that the input tokens are syntactically
70 // TODO: allow Punctuated to be inferred as intra doc link, currently blocked on
71 // https://github.com/rust-lang/rust/issues/62834
72 #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))]
74 macro_rules
! parse_quote
{
76 $
crate::parse_quote
::parse(
77 $
crate::__private
::From
::from(
78 $
crate::__private
::quote
::quote
!($
($tt
)*)
84 ////////////////////////////////////////////////////////////////////////////////
85 // Can parse any type that implements Parse.
87 use crate::parse
::{Parse, ParseStream, Parser, Result}
;
88 use proc_macro2
::TokenStream
;
92 pub fn parse
<T
: ParseQuote
>(token_stream
: TokenStream
) -> T
{
93 let parser
= T
::parse
;
94 match parser
.parse2(token_stream
) {
96 Err(err
) => panic
!("{}", err
),
102 pub trait ParseQuote
: Sized
{
103 fn parse(input
: ParseStream
) -> Result
<Self>;
106 impl<T
: Parse
> ParseQuote
for T
{
107 fn parse(input
: ParseStream
) -> Result
<Self> {
108 <T
as Parse
>::parse(input
)
112 ////////////////////////////////////////////////////////////////////////////////
113 // Any other types that we want `parse_quote!` to be able to parse.
115 use crate::punctuated
::Punctuated
;
116 #[cfg(any(feature = "full", feature = "derive"))]
117 use crate::{attr, Attribute}
;
118 #[cfg(feature = "full")]
119 use crate::{Block, Stmt}
;
121 #[cfg(any(feature = "full", feature = "derive"))]
122 impl ParseQuote
for Attribute
{
123 fn parse(input
: ParseStream
) -> Result
<Self> {
124 if input
.peek(Token
![#]) && input.peek2(Token![!]) {
125 attr
::parsing
::single_parse_inner(input
)
127 attr
::parsing
::single_parse_outer(input
)
132 impl<T
: Parse
, P
: Parse
> ParseQuote
for Punctuated
<T
, P
> {
133 fn parse(input
: ParseStream
) -> Result
<Self> {
134 Self::parse_terminated(input
)
138 #[cfg(feature = "full")]
139 impl ParseQuote
for Vec
<Stmt
> {
140 fn parse(input
: ParseStream
) -> Result
<Self> {
141 Block
::parse_within(input
)