pub mod async_patterns;
pub mod class_hierarchy;
pub mod data_access;
pub mod error_handling;
pub mod logging;
pub mod resource_management;
pub mod state_management;
pub mod type_assertions;
use crate::hint_input::PatternHintInput;
pub const ALL_CATEGORIES: &[&str] = &[
"async_patterns",
"class_hierarchy",
"data_access",
"error_handling",
"logging",
"resource_management",
"state_management",
"type_assertions",
];
pub fn category_for_node_kind(node_kind: &str, _language: &str) -> Option<&'static str> {
if async_patterns::NODE_KINDS.contains(&node_kind) {
Some("async_patterns")
} else if class_hierarchy::NODE_KINDS.contains(&node_kind) {
Some("class_hierarchy")
} else if data_access::NODE_KINDS.contains(&node_kind) {
Some("data_access")
} else if error_handling::NODE_KINDS.contains(&node_kind) {
Some("error_handling")
} else if resource_management::NODE_KINDS.contains(&node_kind) {
Some("resource_management")
} else if state_management::NODE_KINDS.contains(&node_kind) {
Some("state_management")
} else if type_assertions::NODE_KINDS.contains(&node_kind) {
Some("type_assertions")
} else {
None
}
}
pub fn classify_hint(hint: &PatternHintInput, language: &str) -> Vec<&'static str> {
match hint.node_kind.as_str() {
"call_expression" | "call" => {
if async_patterns::matches_callee(&hint.text, language) {
return vec!["async_patterns"];
}
if logging::matches_callee(&hint.text, language) {
return vec!["logging"];
}
if data_access::matches_callee(&hint.text, language) {
return vec!["data_access"];
}
vec![]
}
"macro_invocation" => {
if resource_management::excludes_callee(&hint.text, language)
&& logging::matches_callee(&hint.text, language)
{
return vec!["logging"];
}
vec!["resource_management"]
}
other => category_for_node_kind(other, language)
.map(|c| vec![c])
.unwrap_or_default(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn try_expression_is_error_handling() {
assert_eq!(
category_for_node_kind("try_expression", "rust"),
Some("error_handling")
);
}
#[test]
fn await_expression_is_async_patterns() {
assert_eq!(
category_for_node_kind("await_expression", "rust"),
Some("async_patterns")
);
}
#[test]
fn closure_expression_is_state_management() {
assert_eq!(
category_for_node_kind("closure_expression", "rust"),
Some("state_management")
);
}
#[test]
fn macro_invocation_is_resource_management() {
assert_eq!(
category_for_node_kind("macro_invocation", "rust"),
Some("resource_management")
);
}
#[test]
fn unknown_node_kind_returns_none() {
assert_eq!(category_for_node_kind("unknown_xyz", "rust"), None);
}
#[test]
fn all_categories_has_eight_entries() {
assert_eq!(ALL_CATEGORIES.len(), 8);
assert!(ALL_CATEGORIES.contains(&"data_access"));
}
#[test]
fn logging_is_in_all_categories() {
assert!(ALL_CATEGORIES.contains(&"logging"));
}
#[test]
fn class_hierarchy_is_in_all_categories() {
assert!(ALL_CATEGORIES.contains(&"class_hierarchy"));
}
#[test]
fn class_declaration_is_class_hierarchy() {
assert_eq!(
category_for_node_kind("class_declaration", "typescript"),
Some("class_hierarchy")
);
}
#[test]
fn class_definition_is_class_hierarchy() {
assert_eq!(
category_for_node_kind("class_definition", "python"),
Some("class_hierarchy")
);
}
#[test]
fn impl_item_is_class_hierarchy() {
assert_eq!(
category_for_node_kind("impl_item", "rust"),
Some("class_hierarchy")
);
}
#[test]
fn interface_declaration_is_class_hierarchy() {
assert_eq!(
category_for_node_kind("interface_declaration", "java"),
Some("class_hierarchy")
);
}
#[test]
fn abstract_class_declaration_is_class_hierarchy() {
assert_eq!(
category_for_node_kind("abstract_class_declaration", "typescript"),
Some("class_hierarchy")
);
}
#[test]
fn category_for_node_kind_never_returns_logging() {
for kind in ["call_expression", "call", "macro_invocation"] {
for lang in ["rust", "python", "typescript", "javascript", "go", "java"] {
assert_ne!(
category_for_node_kind(kind, lang),
Some("logging"),
"logging is catalog-only in v0 for category_for_node_kind; \
routing for ({kind}, {lang}) would steal from data_access/resource_management"
);
}
}
}
#[test]
fn call_expression_is_data_access() {
assert_eq!(
category_for_node_kind("call_expression", "typescript"),
Some("data_access")
);
assert_eq!(
category_for_node_kind("call", "python"),
Some("data_access")
);
}
}