🐛 Corrige validación "mut self" y retorno de Self

This commit is contained in:
Manuel Cillero 2025-07-27 01:19:16 +02:00
parent b568db1a02
commit 430ecada41

View file

@ -103,32 +103,16 @@ pub fn builder_fn(_: TokenStream, item: TokenStream) -> TokenStream {
}; };
return expanded.into(); return expanded.into();
} }
// Valida que el método sea público. // Valida que el método es público.
if !matches!(fn_with.vis, syn::Visibility::Public(_)) { if !matches!(fn_with.vis, syn::Visibility::Public(_)) {
return quote_spanned! { return quote_spanned! {
fn_with.sig.ident.span() => compile_error!("expected method to be `pub`"); fn_with.sig.ident.span() => compile_error!("expected method to be `pub`");
} }
.into(); .into();
} }
// Valida que el método devuelva el tipo `Self`. // Valida que el primer argumento es exactamente `mut self`.
if let syn::ReturnType::Type(_, ty) = &fn_with.sig.output {
if let syn::Type::Path(type_path) = &**ty {
let ident = &type_path.path.segments.last().unwrap().ident;
if ident != "Self" {
return quote_spanned! {
fn_with.sig.output.span() => compile_error!("expected return type to be `Self`");
}.into();
}
}
} else {
return quote_spanned! {
fn_with.sig.output.span() => compile_error!("expected method to return `Self`");
}
.into();
}
// Valida que el primer argumento sea `mut self`.
if let Some(syn::FnArg::Receiver(receiver)) = fn_with.sig.inputs.first() { if let Some(syn::FnArg::Receiver(receiver)) = fn_with.sig.inputs.first() {
if receiver.mutability.is_none() { if receiver.mutability.is_none() || receiver.reference.is_some() {
return quote_spanned! { return quote_spanned! {
receiver.span() => compile_error!("expected `mut self` as the first argument"); receiver.span() => compile_error!("expected `mut self` as the first argument");
} }
@ -140,6 +124,27 @@ pub fn builder_fn(_: TokenStream, item: TokenStream) -> TokenStream {
} }
.into(); .into();
} }
// Valida que el método devuelve exactamente `Self`.
if let syn::ReturnType::Type(_, ty) = &fn_with.sig.output {
if let syn::Type::Path(type_path) = ty.as_ref() {
if type_path.qself.is_some() || !type_path.path.is_ident("Self") {
return quote_spanned! { ty.span() =>
compile_error!("expected return type to be exactly `Self`");
}
.into();
}
} else {
return quote_spanned! { ty.span() =>
compile_error!("expected return type to be exactly `Self`");
}
.into();
}
} else {
return quote_spanned! {
fn_with.sig.output.span() => compile_error!("expected method to return `Self`");
}
.into();
}
// Genera el nombre del método alter_...(). // Genera el nombre del método alter_...().
let fn_alter_name_str = fn_with_name_str.replace("with_", "alter_"); let fn_alter_name_str = fn_with_name_str.replace("with_", "alter_");