feat(derive): check component handlers

Make #[slhx::component] compare generated handle symbols with inline #[slhx::handler] functions and fail when a required handler implementation is missing.

req: component/005

req: check/002

req: test/003
This commit is contained in:
slhx agent
2026-05-25 22:30:07 +02:00
parent abe39ec750
commit d223a1d215
2 changed files with 161 additions and 3 deletions
+55
View File
@@ -1,6 +1,61 @@
use std::path::{Path, PathBuf};
use std::process::Command;
#[test]
fn component_macro_reports_missing_handler_implementation() {
// req: component/005 req: check/002 req: test/003
let fixture = Fixture::new("slhx-derive-component-missing-handler-fail");
fixture.write(
"Cargo.toml",
&format!(
r#"[package]
name = "slhx-derive-component-missing-handler-fail"
version = "0.0.0"
edition = "2021"
[lib]
path = "src/lib.rs"
[dependencies]
slhx = {{ path = {:?} }}
"#,
repo_path("slhx")
),
);
fixture.write(
"build.rs",
r#"fn main() {
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
std::fs::write(
out.join("slhx.syms"),
"slhx-syms-v1\nhandle\ttemplates/app.heml::create\tcreate\t1\nhandle\ttemplates/app.heml::delete\tdelete\t2\n",
)
.unwrap();
}
"#,
);
fixture.write(
"src/lib.rs",
r#"#[slhx::component]
mod todos {
#[slhx::handler]
fn create() -> impl slhx::IntoEffect {
slhx::EffectBatch::default()
}
}
"#,
);
let output = check_fixture(&fixture);
assert!(!output.status.success(), "fixture unexpectedly compiled");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("#[slhx::component] missing handler implementation(s): delete"),
"missing component diagnostic in stderr:\n{stderr}"
);
}
#[test]
fn handler_macro_reports_unknown_handle_and_bad_shape() {
// req: derive_handler/001 req: test/003