pub(crate) mod angle;
pub(crate) mod preprocess_helpers;
pub(crate) mod where_process;
pub(crate) use angle::*;
pub(crate) use preprocess_helpers::*;
pub(crate) use where_process::*;
use proc_macro2::{Delimiter, Group, Ident, TokenStream, TokenTree};
use quote::quote;
use syn::ItemTrait;
use crate::diagnostic::compile_error_str;
use crate::scan::Cursor;
pub(crate) fn expand_tokens(
cursor: &mut Cursor, trait_def: &ItemTrait,
) -> Result<Vec<TokenTree>, TokenStream> {
let mut result = vec![];
while !cursor.at_end() {
if cursor.is_punct('#')
&& let Some(TokenTree::Ident(name)) = cursor.peek_at(1)
{
result.push(expand_directive(name, cursor, trait_def)?);
continue;
}
let Some(tt) = cursor.peek() else {
break;
};
if let TokenTree::Group(g) = tt
&& g.delimiter() == Delimiter::Bracket
&& !cursor.prev_is_punct('!')
{
let inner = expand_tokens(
&mut Cursor::new(&g.stream().into_iter().collect::<Vec<_>>()),
trait_def,
)?;
let new_group = Group::new(g.delimiter(), inner.into_iter().collect());
result.push(new_group.into());
cursor.bump();
} else {
result.push(tt.clone());
cursor.bump();
}
}
Ok(result)
}
fn expand_directive(
name: &Ident, cursor: &mut Cursor, trait_def: &ItemTrait,
) -> Result<TokenTree, TokenStream> {
if let Some(TokenTree::Group(args)) = cursor.peek_at(2) {
match args.delimiter() {
Delimiter::Brace => {
cursor.bump(); cursor.bump(); cursor.bump(); expand_single(name, args, trait_def)
}
_ => {
let body_tt = cursor.peek_at(3);
let Some(TokenTree::Group(body)) = body_tt else {
return Err(compile_error_str(&format!(
"`#{}` 后期望 `(args)` + `{{body}}` 或直接 `{{body}}`",
name
)));
};
if body.delimiter() != Delimiter::Brace {
return Err(compile_error_str(&format!(
"`#{}` 后期望 `(args)` + `{{body}}` 或直接 `{{body}}`",
name
)));
}
cursor.bump(); cursor.bump(); cursor.bump(); cursor.bump(); match name.to_string().as_str() {
"fill" => expand_fill(args, body, trait_def),
"delegate" => expand_delegate(args, body, trait_def),
_ => {
let inner = quote! {
#name ! { #args #body #trait_def }
};
Ok(Group::new(Delimiter::Brace, inner).into())
}
}
}
}
} else {
Err(compile_error_str(&format!(
"`#{}` 后期望括号参数 `(args)` 或代码块 `{{body}}`",
name
)))
}
}
fn expand_single(
method_name: &Ident, body: &Group, trait_def: &ItemTrait,
) -> Result<TokenTree, TokenStream> {
let item = get_trait_item(trait_def, method_name)?;
Ok(Group::new(Delimiter::Brace, build_from_item(item, &body.stream())).into())
}
fn expand_many(
args_group: &Group, trait_def: &ItemTrait,
build: impl Fn(&Ident, &syn::TraitItem) -> Result<TokenStream, TokenStream>,
) -> Result<TokenTree, TokenStream> {
let method_names = parse_names_from_tokens(
&args_group.stream().into_iter().collect::<Vec<_>>(),
trait_def,
)?;
let mut methods = TokenStream::new();
for name in &method_names {
let item = get_trait_item(trait_def, name)?;
methods.extend(build(name, item)?);
}
Ok(Group::new(Delimiter::Brace, methods).into())
}
fn expand_fill(
args_group: &Group, body: &Group, trait_def: &ItemTrait,
) -> Result<TokenTree, TokenStream> {
let body_stream = body.stream();
expand_many(args_group, trait_def, |_name, item| {
Ok(build_from_item(item, &body_stream))
})
}
fn expand_delegate(
args_group: &Group, target: &Group, trait_def: &ItemTrait,
) -> Result<TokenTree, TokenStream> {
let target_stream = target.stream();
expand_many(args_group, trait_def, |name, item| {
let syn::TraitItem::Fn(f) = item else {
return Err(compile_error_str(&format!(
"batch-impl: #delegate 只能用于方法,trait `{}` 中的 `{}` 不是方法",
trait_def.ident, name
)));
};
let sig = f.sig.clone();
let call_args = collect_call_args(&sig).map_err(|pat| {
compile_error_str(&format!(
"batch-impl: #delegate 方法 `{}::{}` 的参数 `{}` 无法委托转发:\
仅支持 `self` 与纯标识符模式",
trait_def.ident, name, pat
))
})?;
let body = quote! { (#target_stream) . #name ( #(#call_args),* ) };
Ok(build_from_item(item, &body))
})
}