Skip to main content

normalize_languages/
jq.rs

1//! jq language support.
2
3use crate::{Import, Language, LanguageSymbols};
4use tree_sitter::Node;
5
6/// jq language support.
7pub struct Jq;
8
9impl Language for Jq {
10    fn name(&self) -> &'static str {
11        "jq"
12    }
13    fn extensions(&self) -> &'static [&'static str] {
14        &["jq"]
15    }
16    fn grammar_name(&self) -> &'static str {
17        "jq"
18    }
19
20    fn as_symbols(&self) -> Option<&dyn LanguageSymbols> {
21        Some(self)
22    }
23
24    fn extract_imports(&self, node: &Node, content: &str) -> Vec<Import> {
25        if node.kind() != "import" {
26            return Vec::new();
27        }
28
29        let text = &content[node.byte_range()];
30        let line = node.start_position().row + 1;
31
32        // import "path" as name;
33        if let Some(rest) = text.strip_prefix("import ") {
34            let module = rest.split('"').nth(1).map(|s| s.to_string());
35            let alias = rest
36                .split(" as ")
37                .nth(1)
38                .and_then(|s| s.split(';').next())
39                .map(|s| s.trim().to_string());
40
41            if let Some(module) = module {
42                return vec![Import {
43                    module,
44                    names: Vec::new(),
45                    alias,
46                    is_wildcard: false,
47                    is_relative: true,
48                    line,
49                }];
50            }
51        }
52
53        Vec::new()
54    }
55
56    fn format_import(&self, import: &Import, _names: Option<&[&str]>) -> String {
57        // jq: import "module" as name
58        format!("import \"{}\"", import.module)
59    }
60
61    fn is_test_symbol(&self, symbol: &crate::Symbol) -> bool {
62        let name = symbol.name.as_str();
63        match symbol.kind {
64            crate::SymbolKind::Function | crate::SymbolKind::Method => name.starts_with("test_"),
65            crate::SymbolKind::Module => name == "tests" || name == "test",
66            _ => false,
67        }
68    }
69}
70
71impl LanguageSymbols for Jq {}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use crate::validate_unused_kinds_audit;
77
78    #[test]
79    fn unused_node_kinds_audit() {
80        #[rustfmt::skip]
81        let documented_unused: &[&str] = &[
82            "catch", "elif", "else", "format", "import_", "moduleheader",
83            "programbody",
84        ];
85        validate_unused_kinds_audit(&Jq, documented_unused)
86            .expect("jq unused node kinds audit failed");
87    }
88}