1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use proc_macro::{Ident, TokenStream, TokenTree}; use std::iter; macro_rules! quote { () => { ::proc_macro::TokenStream::new() }; ($($tt:tt)*) => {{ let mut tokens = ::proc_macro::TokenStream::new(); quote_each_token!(tokens $($tt)*); tokens }}; } macro_rules! quote_each_token { ($tokens:ident # $var:ident $($rest:tt)*) => { $crate::quote::Tokens::extend(&mut $tokens, &$var); quote_each_token!($tokens $($rest)*); }; ($tokens:ident $ident:ident $($rest:tt)*) => { <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( &mut $tokens, ::std::iter::once( ::proc_macro::TokenTree::Ident( ::proc_macro::Ident::new( stringify!($ident), ::proc_macro::Span::call_site(), ), ), ), ); quote_each_token!($tokens $($rest)*); }; ($tokens:ident ( $($inner:tt)* ) $($rest:tt)*) => { <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( &mut $tokens, ::std::iter::once( ::proc_macro::TokenTree::Group( ::proc_macro::Group::new( ::proc_macro::Delimiter::Parenthesis, quote!($($inner)*), ), ), ), ); quote_each_token!($tokens $($rest)*); }; ($tokens:ident [ $($inner:tt)* ] $($rest:tt)*) => { <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( &mut $tokens, ::std::iter::once( ::proc_macro::TokenTree::Group( ::proc_macro::Group::new( ::proc_macro::Delimiter::Bracket, quote!($($inner)*), ), ), ), ); quote_each_token!($tokens $($rest)*); }; ($tokens:ident { $($inner:tt)* } $($rest:tt)*) => { <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( &mut $tokens, ::std::iter::once( ::proc_macro::TokenTree::Group( ::proc_macro::Group::new( ::proc_macro::Delimiter::Brace, quote!($($inner)*), ), ), ), ); quote_each_token!($tokens $($rest)*); }; ($tokens:ident $punct:tt $($rest:tt)*) => { <::proc_macro::TokenStream as ::std::iter::Extend<_>>::extend( &mut $tokens, stringify!($punct).parse::<::proc_macro::TokenStream>(), ); quote_each_token!($tokens $($rest)*); }; ($tokens:ident) => {}; } pub trait Tokens { fn extend(tokens: &mut TokenStream, var: &Self); } impl Tokens for Ident { fn extend(tokens: &mut TokenStream, var: &Self) { tokens.extend(iter::once(TokenTree::Ident(var.clone()))); } } impl Tokens for TokenStream { fn extend(tokens: &mut TokenStream, var: &Self) { tokens.extend(var.clone()); } } impl<T: Tokens> Tokens for Option<T> { fn extend(tokens: &mut TokenStream, var: &Self) { if let Some(var) = var { T::extend(tokens, var); } } } impl<T: Tokens> Tokens for &T { fn extend(tokens: &mut TokenStream, var: &Self) { T::extend(tokens, var); } }