use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemStruct, Meta};
pub fn make_struct_chainable(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input_struct = parse_macro_input!(item as ItemStruct);
for attr in &input_struct.attrs {
match &attr.meta {
Meta::List(list) if list.path.is_ident("chain_push") => {
continue;
}
Meta::List(list) if list.path.is_ident("chain_insert") => {
continue;
}
_ => {}
}
}
let methods: Vec<_> = input_struct
.fields
.iter()
.map(|field| {
let function_name = syn::Ident::new(
&format!("with_{}", field.ident.as_ref().unwrap()),
field.ident.as_ref().unwrap().span(),
);
let field_name = &field.ident;
let field_type = &field.ty;
quote! {
pub fn #function_name(mut self, value: #field_type) -> Self {
self.#field_name = value;
self
}
}
})
.collect();
let name = &input_struct.ident;
let result = quote! {
#input_struct
impl #name {
#(#methods)*
}
};
result.into()
}