moxy-derive 0.0.4

derive macros for moxy crate
Documentation
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)*
            }
        })
    }
}