File Index
Files and directories
Sign in
FILE

quote.rs

File preview with syntax highlighting.

linux-6.19.14/rust/macros/quote.rs RUST
  1// SPDX-License-Identifier: Apache-2.0 OR MIT
  2
  3use proc_macro::{TokenStream, TokenTree};
  4
  5pub(crate) trait ToTokens {
  6    fn to_tokens(&self, tokens: &mut TokenStream);
  7}
  8
  9impl<T: ToTokens> ToTokens for Option<T> {
 10    fn to_tokens(&self, tokens: &mut TokenStream) {
 11        if let Some(v) = self {
 12            v.to_tokens(tokens);
 13        }
 14    }
 15}
 16
 17impl ToTokens for proc_macro::Group {
 18    fn to_tokens(&self, tokens: &mut TokenStream) {
 19        tokens.extend([TokenTree::from(self.clone())]);
 20    }
 21}
 22
 23impl ToTokens for proc_macro::Ident {
 24    fn to_tokens(&self, tokens: &mut TokenStream) {
 25        tokens.extend([TokenTree::from(self.clone())]);
 26    }
 27}
 28
 29impl ToTokens for TokenTree {
 30    fn to_tokens(&self, tokens: &mut TokenStream) {
 31        tokens.extend([self.clone()]);
 32    }
 33}
 34
 35impl ToTokens for TokenStream {
 36    fn to_tokens(&self, tokens: &mut TokenStream) {
 37        tokens.extend(self.clone());
 38    }
 39}
 40
 41/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
 42/// the given span.
 43///
 44/// This is a similar to the
 45/// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the
 46/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
 47macro_rules! quote_spanned {
 48    ($span:expr => $($tt:tt)*) => {{
 49        let mut tokens = ::proc_macro::TokenStream::new();
 50        {
 51            #[allow(unused_variables)]
 52            let span = $span;
 53            quote_spanned!(@proc tokens span $($tt)*);
 54        }
 55        tokens
 56    }};
 57    (@proc $v:ident $span:ident) => {};
 58    (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
 59        $crate::quote::ToTokens::to_tokens(&$id, &mut $v);
 60        quote_spanned!(@proc $v $span $($tt)*);
 61    };
 62    (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
 63        for token in $id {
 64            $crate::quote::ToTokens::to_tokens(&token, &mut $v);
 65        }
 66        quote_spanned!(@proc $v $span $($tt)*);
 67    };
 68    (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
 69        #[allow(unused_mut)]
 70        let mut tokens = ::proc_macro::TokenStream::new();
 71        quote_spanned!(@proc tokens $span $($inner)*);
 72        $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 73            ::proc_macro::Delimiter::Parenthesis,
 74            tokens,
 75        ))]);
 76        quote_spanned!(@proc $v $span $($tt)*);
 77    };
 78    (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
 79        let mut tokens = ::proc_macro::TokenStream::new();
 80        quote_spanned!(@proc tokens $span $($inner)*);
 81        $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 82            ::proc_macro::Delimiter::Bracket,
 83            tokens,
 84        ))]);
 85        quote_spanned!(@proc $v $span $($tt)*);
 86    };
 87    (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
 88        let mut tokens = ::proc_macro::TokenStream::new();
 89        quote_spanned!(@proc tokens $span $($inner)*);
 90        $v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 91            ::proc_macro::Delimiter::Brace,
 92            tokens,
 93        ))]);
 94        quote_spanned!(@proc $v $span $($tt)*);
 95    };
 96    (@proc $v:ident $span:ident :: $($tt:tt)*) => {
 97        $v.extend([::proc_macro::Spacing::Joint, ::proc_macro::Spacing::Alone].map(|spacing| {
 98            ::proc_macro::TokenTree::Punct(::proc_macro::Punct::new(':', spacing))
 99        }));
100        quote_spanned!(@proc $v $span $($tt)*);
101    };
102    (@proc $v:ident $span:ident : $($tt:tt)*) => {
103        $v.extend([::proc_macro::TokenTree::Punct(
104            ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone),
105        )]);
106        quote_spanned!(@proc $v $span $($tt)*);
107    };
108    (@proc $v:ident $span:ident , $($tt:tt)*) => {
109        $v.extend([::proc_macro::TokenTree::Punct(
110            ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone),
111        )]);
112        quote_spanned!(@proc $v $span $($tt)*);
113    };
114    (@proc $v:ident $span:ident @ $($tt:tt)*) => {
115        $v.extend([::proc_macro::TokenTree::Punct(
116            ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone),
117        )]);
118        quote_spanned!(@proc $v $span $($tt)*);
119    };
120    (@proc $v:ident $span:ident ! $($tt:tt)*) => {
121        $v.extend([::proc_macro::TokenTree::Punct(
122            ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone),
123        )]);
124        quote_spanned!(@proc $v $span $($tt)*);
125    };
126    (@proc $v:ident $span:ident ; $($tt:tt)*) => {
127        $v.extend([::proc_macro::TokenTree::Punct(
128            ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone),
129        )]);
130        quote_spanned!(@proc $v $span $($tt)*);
131    };
132    (@proc $v:ident $span:ident + $($tt:tt)*) => {
133        $v.extend([::proc_macro::TokenTree::Punct(
134            ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone),
135        )]);
136        quote_spanned!(@proc $v $span $($tt)*);
137    };
138    (@proc $v:ident $span:ident = $($tt:tt)*) => {
139        $v.extend([::proc_macro::TokenTree::Punct(
140            ::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone),
141        )]);
142        quote_spanned!(@proc $v $span $($tt)*);
143    };
144    (@proc $v:ident $span:ident # $($tt:tt)*) => {
145        $v.extend([::proc_macro::TokenTree::Punct(
146            ::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone),
147        )]);
148        quote_spanned!(@proc $v $span $($tt)*);
149    };
150    (@proc $v:ident $span:ident & $($tt:tt)*) => {
151        $v.extend([::proc_macro::TokenTree::Punct(
152            ::proc_macro::Punct::new('&', ::proc_macro::Spacing::Alone),
153        )]);
154        quote_spanned!(@proc $v $span $($tt)*);
155    };
156    (@proc $v:ident $span:ident _ $($tt:tt)*) => {
157        $v.extend([::proc_macro::TokenTree::Ident(
158            ::proc_macro::Ident::new("_", $span),
159        )]);
160        quote_spanned!(@proc $v $span $($tt)*);
161    };
162    (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
163        $v.extend([::proc_macro::TokenTree::Ident(
164            ::proc_macro::Ident::new(stringify!($id), $span),
165        )]);
166        quote_spanned!(@proc $v $span $($tt)*);
167    };
168}
169
170/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
171/// mixed site span ([`Span::mixed_site()`]).
172///
173/// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro
174/// from the `quote` crate but provides only just enough functionality needed by the current
175/// `macros` crate.
176///
177/// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site
178macro_rules! quote {
179    ($($tt:tt)*) => {
180        quote_spanned!(::proc_macro::Span::mixed_site() => $($tt)*)
181    }
182}
~/ Read-only file preview.