use proc_macro2::{Delimiter, Group, TokenTree};
use proc_macro2::{Literal, TokenStream};
use syn::{parse_str, parse2};
use crate::builder::build_string;
use crate::models::RenderType;
use crate::parser::TweldDsl;
pub(crate) const IDENT_EMPTY_MSG: &str = "The identifier is an empty string!";
pub fn scan_tokens(input: TokenStream) -> syn::Result<TokenStream> {
let mut output = Vec::new();
let mut tokens = input.into_iter().peekable();
while let Some(tree) = tokens.next() {
match tree {
TokenTree::Punct(ref p) if p.as_char() == '@' => {
if let Some(TokenTree::Group(grp)) = tokens.peek() {
let span = grp.span();
if grp.delimiter() == Delimiter::Bracket {
let Some(TokenTree::Group(bracket_group)) = tokens.next() else {
return Err(syn::Error::new(
span,
"There was an error when consuming the bracket group!",
));
};
let dsl: TweldDsl = parse2(bracket_group.stream())?;
let result = build_string(dsl.tokens);
match dsl.render_type {
RenderType::Identifier => {
let result = result.replace(" ", "");
if result.is_empty() {
return Err(syn::Error::new(span, IDENT_EMPTY_MSG));
}
let identifier =
parse_str::<proc_macro2::Ident>(&result).or_else(|_| {
parse_str::<proc_macro2::Ident>(&format!("r#{result}"))
})?;
output.push(TokenTree::Ident(identifier));
}
RenderType::StringLiteral => {
output.push(TokenTree::Literal(Literal::string(&result)));
}
}
continue;
}
}
output.push(tree);
}
TokenTree::Group(g) => {
let inner_expanded = scan_tokens(g.stream())?;
let mut new_group = Group::new(g.delimiter(), inner_expanded);
new_group.set_span(g.span());
output.push(TokenTree::Group(new_group));
}
t => {
output.push(t);
}
}
}
Ok(TokenStream::from_iter(output))
}