1 | use crate::attr::{self, Then}; |
2 | use crate::error::{Error, Result}; |
3 | use crate::{constfn, expr, iter, token}; |
4 | use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; |
5 | use std::iter::FromIterator; |
6 | |
7 | pub fn cfg(introducer: &str, args: TokenStream, input: TokenStream) -> TokenStream { |
8 | try_cfg(introducer, args, input).unwrap_or_else(op:Error::into_compile_error) |
9 | } |
10 | |
11 | fn try_cfg(introducer: &str, args: TokenStream, input: TokenStream) -> Result<TokenStream> { |
12 | let introducer: Ident = Ident::new(string:introducer, Span::call_site()); |
13 | |
14 | let mut full_args: TokenStream = TokenStream::from(TokenTree::Ident(introducer)); |
15 | if !args.is_empty() { |
16 | full_args.extend(iter:std::iter::once(TokenTree::Group(Group::new( |
17 | Delimiter::Parenthesis, |
18 | stream:args, |
19 | )))); |
20 | } |
21 | |
22 | let ref mut full_args: &mut IterImpl = iter::new(tokens:full_args); |
23 | let expr: Expr = expr::parse(iter:full_args)?; |
24 | token::parse_end(iter:full_args)?; |
25 | |
26 | if expr.eval(rustc:crate::RUSTVERSION) { |
27 | Ok(input) |
28 | } else { |
29 | Ok(TokenStream::new()) |
30 | } |
31 | } |
32 | |
33 | pub fn try_attr(args: attr::Args, input: TokenStream) -> Result<TokenStream> { |
34 | if !args.condition.eval(crate::RUSTVERSION) { |
35 | return Ok(input); |
36 | } |
37 | |
38 | match args.then { |
39 | Then::Const(const_token) => constfn::insert_const(input, const_token), |
40 | Then::Attribute(then) => { |
41 | // #[cfg_attr(all(), #then)] |
42 | Ok(TokenStream::from_iter( |
43 | vec![ |
44 | TokenTree::Punct(Punct::new('#' , Spacing::Alone)), |
45 | TokenTree::Group(Group::new( |
46 | Delimiter::Bracket, |
47 | TokenStream::from_iter(vec![ |
48 | TokenTree::Ident(Ident::new("cfg_attr" , Span::call_site())), |
49 | TokenTree::Group(Group::new( |
50 | Delimiter::Parenthesis, |
51 | TokenStream::from_iter( |
52 | vec![ |
53 | TokenTree::Ident(Ident::new("all" , Span::call_site())), |
54 | TokenTree::Group(Group::new( |
55 | Delimiter::Parenthesis, |
56 | TokenStream::new(), |
57 | )), |
58 | TokenTree::Punct(Punct::new(',' , Spacing::Alone)), |
59 | ] |
60 | .into_iter() |
61 | .chain(then), |
62 | ), |
63 | )), |
64 | ]), |
65 | )), |
66 | ] |
67 | .into_iter() |
68 | .chain(input), |
69 | )) |
70 | } |
71 | } |
72 | } |
73 | |