use proc_macro2::{Group, Ident, TokenStream, TokenTree};
use crate::ast::parse_grouped_fresh;
pub(crate) fn sweep_fresh_names(tokens: TokenStream) -> TokenStream {
let mut groups: Vec<(usize, usize)> = vec![];
collect_grouped_fresh(&tokens, &mut groups);
if groups.is_empty() {
return tokens;
}
groups.sort_unstable();
groups.dedup();
let map: std::collections::HashMap<(usize, usize), usize> =
groups.iter().enumerate().map(|(k, &gi)| (gi, k)).collect();
replace_grouped_fresh(tokens, &map)
}
pub(crate) fn collect_grouped_fresh(
tokens: &TokenStream, out: &mut Vec<(usize, usize)>,
) {
for tt in tokens.clone() {
match tt {
TokenTree::Ident(id) => {
if let Some(gi) = parse_grouped_fresh(&id.to_string()) {
out.push(gi);
}
}
TokenTree::Group(g) => {
let inner = g.stream();
collect_grouped_fresh(&inner, out);
}
_ => {}
}
}
}
pub(crate) fn replace_grouped_fresh(
tokens: TokenStream, map: &std::collections::HashMap<(usize, usize), usize>,
) -> TokenStream {
let mut out = vec![];
for tt in tokens {
match tt {
TokenTree::Ident(id) => {
let s = id.to_string();
if let Some(&k) = parse_grouped_fresh(&s).and_then(|gi| map.get(&gi))
{
let name = format!("_Param_{}_BatchGen_", k);
out.push(TokenTree::Ident(Ident::new(&name, id.span())));
} else {
out.push(TokenTree::Ident(id));
}
}
TokenTree::Group(g) => {
let inner = g.stream();
let mut new_g =
Group::new(g.delimiter(), replace_grouped_fresh(inner, map));
new_g.set_span(g.span());
out.push(TokenTree::Group(new_g));
}
other => out.push(other),
}
}
out.into_iter().collect()
}