Expand fn_builder to generic functions

This commit is contained in:
Manuel Cillero 2024-03-16 21:12:03 +01:00
parent 36c931486d
commit 400a492311

View file

@ -15,18 +15,35 @@ pub fn html(input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn fn_builder(_: TokenStream, item: TokenStream) -> TokenStream { pub fn fn_builder(_: TokenStream, item: TokenStream) -> TokenStream {
let fn_item = parse_macro_input!(item as ItemFn); let fn_alter = parse_macro_input!(item as ItemFn);
let fn_alter_name = fn_item.sig.ident.to_string(); let fn_alter_name = fn_alter.sig.ident.to_string();
if !fn_alter_name.starts_with("alter_") { if !fn_alter_name.starts_with("alter_") {
let expanded = quote_spanned! { let expanded = quote_spanned! {
fn_item.sig.ident.span() => fn_alter.sig.ident.span() =>
compile_error!("expected a \"pub fn alter_...() -> &mut Self\" method"); compile_error!("expected a \"pub fn alter_...() -> &mut Self\" method");
}; };
return expanded.into(); return expanded.into();
} }
let args: Vec<String> = fn_item let fn_with_name = fn_alter_name.replace("alter_", "with_");
let fn_with_generics = if fn_alter.sig.generics.params.is_empty() {
fn_with_name.to_owned()
} else {
let g = &fn_alter.sig.generics;
concat_string!(fn_with_name, quote! { #g }.to_string())
};
let where_clause = fn_alter
.sig
.generics
.where_clause
.as_ref()
.map_or(String::new(), |where_clause| {
concat_string!(quote! { #where_clause }.to_string(), " ")
});
let args: Vec<String> = fn_alter
.sig .sig
.inputs .inputs
.iter() .iter()
@ -34,7 +51,7 @@ pub fn fn_builder(_: TokenStream, item: TokenStream) -> TokenStream {
.map(|arg| arg.to_token_stream().to_string()) .map(|arg| arg.to_token_stream().to_string())
.collect(); .collect();
let param: Vec<String> = args let params: Vec<String> = args
.iter() .iter()
.map(|arg| { .map(|arg| {
arg.split_whitespace() arg.split_whitespace()
@ -45,12 +62,10 @@ pub fn fn_builder(_: TokenStream, item: TokenStream) -> TokenStream {
}) })
.collect(); .collect();
let fn_with_name = fn_alter_name.replace("alter_", "with_");
#[rustfmt::skip] #[rustfmt::skip]
let fn_with = parse_str::<ItemFn>(concat_string!(" let fn_with = parse_str::<ItemFn>(concat_string!("
pub fn ", fn_with_name, "(mut self, ", args.join(", "), ") -> Self { pub fn ", fn_with_generics, "(mut self, ", args.join(", "), ") -> Self ", where_clause, "{
self.", fn_alter_name, "(", param.join(", "), "); self.", fn_alter_name, "(", params.join(", "), ");
self self
} }
").as_str()).unwrap(); ").as_str()).unwrap();
@ -64,8 +79,6 @@ pub fn fn_builder(_: TokenStream, item: TokenStream) -> TokenStream {
"</p>" "</p>"
); );
let fn_alter = fn_item.into_token_stream();
let expanded = quote! { let expanded = quote! {
#[doc(hidden)] #[doc(hidden)]
#fn_with #fn_with