use proc_macro2::TokenStream;
use quote::quote;
use crate::{Render, core::Field, params};
use super::syntax::ForwardSyntax;
#[derive(Clone, Default)]
pub struct StructSyntax;
impl Render for StructSyntax {
type Args = params::StructParams;
fn render(&self, args: Self::Args) -> syn::Result<TokenStream> {
let ident = &args.input.ident;
let (impl_generics, type_generics, where_generics) = args.input.generics.split_for_impl();
let fields: Vec<_> = args
.data
.fields
.iter()
.enumerate()
.map(|(i, field)| Field::parse(i, field))
.collect::<syn::Result<Vec<_>>>()?;
let mut methods = Vec::new();
for field in &fields {
let fwd = ForwardSyntax::parse(field.attrs())?;
if fwd.sigs.is_empty() {
continue;
}
let field_name = field.name();
for s in &fwd.sigs {
let method_name = &s.ident;
let output = &s.output;
let inputs = &s.inputs;
let arg_names: Vec<_> = s
.inputs
.iter()
.filter_map(|arg| match arg {
syn::FnArg::Typed(pat) => Some(&*pat.pat),
_ => None,
})
.collect();
methods.push(quote! {
pub fn #method_name(#inputs) #output {
self.#field_name.#method_name(#(#arg_names),*)
}
});
}
}
Ok(quote! {
impl #impl_generics #ident #type_generics #where_generics {
#(#methods)*
}
})
}
}