code_analyze_core/languages/
javascript.rs1pub const ELEMENT_QUERY: &str = r"
5(function_declaration) @function
6(class_declaration) @class
7(method_definition) @function
8(generator_function_declaration) @function
9
10";
11
12pub const CALL_QUERY: &str = r"
14(call_expression
15 function: (identifier) @call)
16(call_expression
17 function: (member_expression property: (property_identifier) @call))
18";
19
20pub const IMPORT_QUERY: &str = r#"
22(import_statement) @import_path
23(call_expression
24 function: (identifier) @_fn (#eq? @_fn "require")
25 arguments: (arguments (string) @import_path))
26"#;
27
28use tree_sitter::Node;
35
36#[must_use]
38pub fn extract_inheritance(node: &Node, source: &str) -> Vec<String> {
39 let mut inherits = Vec::new();
40 for i in 0..node.named_child_count() {
42 if let Some(child) = node.named_child(u32::try_from(i).unwrap_or(u32::MAX))
43 && child.kind() == "class_heritage"
44 {
45 for j in 0..child.named_child_count() {
47 if let Some(clause) = child.named_child(u32::try_from(j).unwrap_or(u32::MAX))
48 && clause.kind() == "extends_clause"
49 && let Some(value) = clause.child_by_field_name("value")
50 {
51 let text = &source[value.start_byte()..value.end_byte()];
52 inherits.push(format!("extends {text}"));
53 }
54 }
55 }
56 }
57 inherits
58}
59
60#[cfg(all(test, feature = "lang-javascript"))]
61mod tests {
62 use tree_sitter::Parser;
63
64 fn parse_js(src: &str) -> tree_sitter::Tree {
65 let mut parser = Parser::new();
66 parser
67 .set_language(&tree_sitter_javascript::LANGUAGE.into())
68 .unwrap();
69 parser.parse(src, None).unwrap()
70 }
71
72 fn find_node_by_kind<'a>(
73 node: tree_sitter::Node<'a>,
74 kind: &str,
75 ) -> Option<tree_sitter::Node<'a>> {
76 if node.kind() == kind {
77 return Some(node);
78 }
79 for i in 0..node.child_count() {
80 if let Some(child) = node.child(u32::try_from(i).unwrap_or(u32::MAX)) {
81 if let Some(found) = find_node_by_kind(child, kind) {
82 return Some(found);
83 }
84 }
85 }
86 None
87 }
88
89 #[test]
90 fn test_function_declaration() {
91 let src = "function greet() { return 42; }";
92 let tree = parse_js(src);
93 let root = tree.root_node();
94 let func = find_node_by_kind(root, "function_declaration");
95 assert!(func.is_some(), "expected to find function_declaration");
96 }
97
98 #[test]
99 fn test_arrow_function() {
100 let src = "const add = (a, b) => a + b;";
101 let tree = parse_js(src);
102 let root = tree.root_node();
103 let arrow = find_node_by_kind(root, "arrow_function");
104 assert!(arrow.is_some(), "expected to find arrow_function");
105 }
106
107 #[test]
108 fn test_class_declaration() {
109 let src = "class Foo extends Bar { method() {} }";
110 let tree = parse_js(src);
111 let root = tree.root_node();
112 let class = find_node_by_kind(root, "class_declaration");
113 assert!(class.is_some(), "expected to find class_declaration");
114 }
115
116 #[test]
117 fn test_es_import() {
118 let src = "import {x} from 'module';";
119 let tree = parse_js(src);
120 let root = tree.root_node();
121 let import = find_node_by_kind(root, "import_statement");
122 assert!(import.is_some(), "expected to find import_statement");
123 }
124
125 #[test]
126 fn test_commonjs_require() {
127 let src = "const lib = require('lib');";
128 let tree = parse_js(src);
129 let root = tree.root_node();
130 let call = find_node_by_kind(root, "call_expression");
131 assert!(call.is_some(), "expected to find call_expression");
132 }
133}