use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::ItemTrait;
use crate::TraitBounds;
use crate::apply::err_ty;
use crate::ast::{Expand, Op, Ty, TyKind, reset_fresh_counter};
use crate::codegen::generate_impl;
use crate::parse::parse_item;
use crate::util::Cursor;
#[allow(clippy::too_many_arguments)]
pub(crate) fn parse_batch_trait_entry(
cursor: &mut Cursor, top_level: Op, trait_full_path: &TokenStream,
trait_last_ident: &Ident, is_unsafe_trait: bool, start_trait: Option<ItemTrait>,
trait_bounds: &TraitBounds, trait_param_names: &[Ident],
) -> TokenStream {
let mut tys = vec![];
if cursor.is_punct(',') {
tys.push(err_ty("batch-impl: spec list cannot start with `,`"));
}
while let Some(ty) = parse_item(cursor, top_level, trait_last_ident.into()) {
reset_fresh_counter();
let mut queue = vec![ty];
while let Some(item) = queue.pop() {
match item.expand() {
Expand::Many(expanded) => {
for e in expanded.into_iter().rev() {
queue.push(e);
}
}
Expand::Leaf(leaf) => tys.push(leaf),
}
}
}
fn collect_errors(ty: &Ty, out: &mut Vec<TokenStream>) {
if let Ty { kind: TyKind::Error(e), .. } = ty {
out.push(e.0.clone());
}
ty.clone().map_children(&mut |child| {
collect_errors(&child, out);
child
});
}
let mut errors = vec![];
for t in &tys {
collect_errors(t, &mut errors);
}
if !errors.is_empty() {
let mut out = TokenStream::new();
for e in errors {
out.extend(e);
}
return out;
}
let mut impls = start_trait.map_or(quote![], |t| quote![#t]);
for t in tys {
impls.extend(generate_impl(
t,
trait_full_path,
is_unsafe_trait,
trait_bounds,
trait_param_names,
));
}
impls
}