use crate::attr::{self, Then};
use crate::error::{Error, Result};
use crate::{constfn, expr, iter, token};
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
pub fn cfg(introducer: &str, args: TokenStream, input: TokenStream) -> TokenStream {
try_cfg(introducer, args, input).unwrap_or_else(Error::into_compile_error)
}
fn try_cfg(introducer: &str, args: TokenStream, input: TokenStream) -> Result<TokenStream> {
let introducer = Ident::new(introducer, Span::call_site());
let mut full_args = TokenStream::from(TokenTree::Ident(introducer));
if !args.is_empty() {
full_args.extend(std::iter::once(TokenTree::Group(Group::new(
Delimiter::Parenthesis,
args,
))));
}
let ref mut full_args = iter::new(full_args);
let expr = expr::parse(full_args)?;
token::parse_end(full_args)?;
if expr.eval(crate::RUSTVERSION) {
Ok(input)
} else {
Ok(TokenStream::new())
}
}
pub fn try_attr(args: attr::Args, input: TokenStream) -> Result<TokenStream> {
if !args.condition.eval(crate::RUSTVERSION) {
return Ok(input);
}
match args.then {
Then::Const(const_token) => constfn::insert_const(input, const_token),
Then::Attribute(then) => {
Ok(TokenStream::from_iter(
vec![
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
TokenTree::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("cfg_attr", Span::call_site())),
TokenTree::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::from_iter(
vec![
TokenTree::Ident(Ident::new("all", Span::call_site())),
TokenTree::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::new(),
)),
TokenTree::Punct(Punct::new(',', Spacing::Alone)),
]
.into_iter()
.chain(then),
),
)),
]),
)),
]
.into_iter()
.chain(input),
))
}
}
}