use std::collections::BTreeMap;
use cratestack_core::Schema;
use cratestack_core::route_naming::{pluralize, to_snake_case};
use crate::diagnostics::{SchemaError, span_error};
fn model_handler_stems(model_name: &str) -> [(&'static str, String); 5] {
let snake = to_snake_case(model_name);
let plural = pluralize(&snake);
[
("list", format!("list_{plural}")),
("create", format!("create_{plural}")),
("get", format!("get_{snake}")),
("update", format!("update_{snake}")),
("delete", format!("delete_{snake}")),
]
}
pub(super) fn validate_procedure_model_handler_collisions(
schema: &Schema,
) -> Result<(), SchemaError> {
if schema.models.is_empty() || schema.procedures.is_empty() {
return Ok(());
}
let mut generated: BTreeMap<String, (&str, &'static str)> = BTreeMap::new();
for model in &schema.models {
for (operation, stem) in model_handler_stems(&model.name) {
generated
.entry(format!("handle_{stem}"))
.or_insert((model.name.as_str(), operation));
generated
.entry(format!("handle_{stem}_dispatch"))
.or_insert((model.name.as_str(), operation));
}
}
for procedure in &schema.procedures {
let snake = to_snake_case(&procedure.name);
for handler in [
format!("handle_{snake}"),
format!("handle_{snake}_dispatch"),
] {
let Some((model_name, operation)) = generated.get(handler.as_str()) else {
continue;
};
return Err(span_error(
format!(
"procedure `{procedure}` collides with the generated `{operation}` CRUD \
handler for model `{model_name}` — both emit `{handler}` into the axum \
module generated by `include_server_schema!` (and the matching RPC \
dispatch arm), which fails to compile as `error[E0428]`; rename the \
procedure",
procedure = procedure.name,
),
procedure.name_span,
));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn model_stems_track_the_macro_naming_scheme() {
let stems = model_handler_stems("SubOrder");
let stems: Vec<&str> = stems.iter().map(|(_, stem)| stem.as_str()).collect();
assert_eq!(
stems,
vec![
"list_sub_orders",
"create_sub_orders",
"get_sub_order",
"update_sub_order",
"delete_sub_order",
]
);
}
}