fix(derive): require generated handler symbols

Make #[slhx::handler] fail when slhx.syms is missing instead of silently skipping generated handle checks. Add compile-fail coverage with an actionable build.rs hint.

req: build/003

req: test/003
This commit is contained in:
slhx agent
2026-05-25 21:26:48 +02:00
parent dca26511cc
commit 87a19fd923
2 changed files with 99 additions and 33 deletions
+48 -33
View File
@@ -8,39 +8,54 @@ pub fn handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
let function = parse_macro_input!(item as ItemFn);
let name = function.sig.ident.to_string();
if let Some(syms_path) = syms_path() {
if syms_path.exists() {
if !syms_contains_handle(&syms_path, &name) {
let message = format!(
"unknown slhx handle `{name}`; add `data-slhx-handle=\"{name}\"` to a template or rename this handler"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
if !has_form_param(&function) && !has_non_unit_return(&function) {
let message = format!(
"slhx handler `{name}` must accept a form/context parameter or return a value implementing IntoEffect"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
if handle_requires_form(&syms_path, &name) && !has_form_param(&function) {
let message = format!(
"slhx handler `{name}` handles a generated form and must accept slhx::Form<_>"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
}
let Some(syms_path) = syms_path() else {
let message = "#[slhx::handler] requires OUT_DIR; run inside a Cargo crate with slhx_build::app() in build.rs";
return quote!(
#function
compile_error!(#message);
)
.into();
};
if !syms_path.exists() {
let message = format!(
"#[slhx::handler] could not find {}; add slhx_build::app().run()? to build.rs or check template generation",
syms_path.display()
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
if !syms_contains_handle(&syms_path, &name) {
let message = format!(
"unknown slhx handle `{name}`; add `data-slhx-handle=\"{name}\"` to a template or rename this handler"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
if !has_form_param(&function) && !has_non_unit_return(&function) {
let message = format!(
"slhx handler `{name}` must accept a form/context parameter or return a value implementing IntoEffect"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
if handle_requires_form(&syms_path, &name) && !has_form_param(&function) {
let message = format!(
"slhx handler `{name}` handles a generated form and must accept slhx::Form<_>"
);
return quote!(
#function
compile_error!(#message);
)
.into();
}
quote!(#function).into()