use quote::quote; pub fn builder(input: proc_macro2::TokenStream) -> syn::Result { let input: syn::DeriveInput = syn::parse2(input)?; let ident = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let data = match &input.data { syn::Data::Struct(data) => data, _ => { return Err(syn::Error::new_spanned( input, "this macro can only be used on a struct", )) } }; let fns = data .fields .iter() .filter_map(|field| { let field_ident = &field.ident; let field_ty = &field.ty; if field.attrs.iter().any(|attr| attr.path.is_ident("builder")) { Some((field_ident, field_ty)) } else { None } }) .map(|(field_ident, field_ty)| { quote! { pub fn #field_ident(mut self, #field_ident: impl Into<#field_ty>) -> #ident#ty_generics { self.#field_ident = #field_ident.into(); self } } }); Ok(quote! { impl#impl_generics #ident#ty_generics #where_clause { #(#fns)* } }) }