Skip to main content

normalize_languages/
kdl.rs

1//! KDL (KDocument Language) support.
2
3use crate::{ContainerBody, Language, LanguageSymbols};
4use tree_sitter::Node;
5
6/// KDL language support.
7pub struct Kdl;
8
9impl Language for Kdl {
10    fn name(&self) -> &'static str {
11        "KDL"
12    }
13    fn extensions(&self) -> &'static [&'static str] {
14        &["kdl"]
15    }
16    fn grammar_name(&self) -> &'static str {
17        "kdl"
18    }
19
20    fn as_symbols(&self) -> Option<&dyn LanguageSymbols> {
21        Some(self)
22    }
23
24    fn container_body<'a>(&self, node: &'a Node<'a>) -> Option<Node<'a>> {
25        // KDL: node → node_no_terminator → children field (node_children: "{ ... }")
26        let mut c = node.walk();
27        for child in node.children(&mut c) {
28            if child.kind() == "node_no_terminator" {
29                return child.child_by_field_name("children");
30            }
31        }
32        None
33    }
34
35    fn analyze_container_body(
36        &self,
37        body_node: &Node,
38        content: &str,
39        inner_indent: &str,
40    ) -> Option<ContainerBody> {
41        // node_children is "{ ... }" — use brace body analysis
42        crate::body::analyze_brace_body(body_node, content, inner_indent)
43    }
44
45    fn node_name<'a>(&self, node: &Node, content: &'a str) -> Option<&'a str> {
46        // First child is typically the identifier
47        let mut cursor = node.walk();
48        for child in node.children(&mut cursor) {
49            if child.kind() == "identifier" || child.kind() == "string" {
50                return Some(&content[child.byte_range()]);
51            }
52        }
53        None
54    }
55}
56
57impl LanguageSymbols for Kdl {}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::validate_unused_kinds_audit;
63
64    #[test]
65    fn unused_node_kinds_audit() {
66        #[rustfmt::skip]
67        let documented_unused: &[&str] = &[
68            "annotation_type",       // Type annotations
69            "identifier_string",     // Identifiers as strings
70            "multi_line_string_body", // Multi-line string content
71            "type",                  // Type annotations
72        ];
73        validate_unused_kinds_audit(&Kdl, documented_unused)
74            .expect("KDL unused node kinds audit failed");
75    }
76}