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 
cfg(introducer: &str, args: TokenStream, input: TokenStream) -> TokenStream7 pub fn cfg(introducer: &str, args: TokenStream, input: TokenStream) -> TokenStream {
8     try_cfg(introducer, args, input).unwrap_or_else(Error::into_compile_error)
9 }
10 
try_cfg(introducer: &str, args: TokenStream, input: TokenStream) -> Result<TokenStream>11 fn try_cfg(introducer: &str, args: TokenStream, input: TokenStream) -> Result<TokenStream> {
12     let introducer = Ident::new(introducer, Span::call_site());
13 
14     let mut full_args = TokenStream::from(TokenTree::Ident(introducer));
15     if !args.is_empty() {
16         full_args.extend(std::iter::once(TokenTree::Group(Group::new(
17             Delimiter::Parenthesis,
18             args,
19         ))));
20     }
21 
22     let ref mut full_args = iter::new(full_args);
23     let expr = expr::parse(full_args)?;
24     token::parse_end(full_args)?;
25 
26     if expr.eval(crate::RUSTVERSION) {
27         Ok(input)
28     } else {
29         Ok(TokenStream::new())
30     }
31 }
32 
try_attr(args: attr::Args, input: TokenStream) -> Result<TokenStream>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