code_analyze_core/languages/
rust.rs1use tree_sitter::Node;
4
5pub const ELEMENT_QUERY: &str = r"
7(function_item
8 name: (identifier) @func_name
9 parameters: (parameters) @params) @function
10(struct_item) @class
11(enum_item) @class
12(trait_item) @class
13";
14
15pub const CALL_QUERY: &str = r"
17(call_expression function: (identifier) @call)
18(call_expression function: (field_expression field: (field_identifier) @call))
19(call_expression function: (scoped_identifier name: (identifier) @call))
20";
21
22pub const REFERENCE_QUERY: &str = r"
24(type_identifier) @type_ref
25";
26
27pub const IMPORT_QUERY: &str = r"
29(use_declaration argument: (_) @import_path) @import
30";
31
32pub const IMPL_TRAIT_QUERY: &str = r"
37(impl_item
38 trait: (type_identifier) @trait_name
39 type: (type_identifier) @impl_type)
40";
41
42pub const IMPL_QUERY: &str = r"
44(impl_item
45 type: (type_identifier) @impl_type
46 body: (declaration_list
47 (function_item
48 name: (identifier) @method_name
49 parameters: (parameters) @method_params) @method))
50";
51
52#[must_use]
54pub fn extract_function_name(node: &Node, source: &str, _query_name: &str) -> Option<String> {
55 if node.kind() != "function_item" {
56 return None;
57 }
58 node.child_by_field_name("name").and_then(|n| {
59 let start = n.start_byte();
60 let end = n.end_byte();
61 if end <= source.len() {
62 Some(source[start..end].to_string())
63 } else {
64 None
65 }
66 })
67}
68
69#[must_use]
71pub fn find_method_for_receiver(
72 node: &Node,
73 source: &str,
74 _depth: Option<usize>,
75) -> Option<String> {
76 if node.kind() != "method_item" && node.kind() != "function_item" {
77 return None;
78 }
79 node.child_by_field_name("name").and_then(|n| {
80 let start = n.start_byte();
81 let end = n.end_byte();
82 if end <= source.len() {
83 Some(source[start..end].to_string())
84 } else {
85 None
86 }
87 })
88}
89
90#[must_use]
92pub fn find_receiver_type(node: &Node, source: &str) -> Option<String> {
93 if node.kind() != "impl_item" {
94 return None;
95 }
96 node.child_by_field_name("type").and_then(|n| {
97 let start = n.start_byte();
98 let end = n.end_byte();
99 if end <= source.len() {
100 Some(source[start..end].to_string())
101 } else {
102 None
103 }
104 })
105}
106
107#[must_use]
111pub fn extract_inheritance(_node: &Node, _source: &str) -> Vec<String> {
112 Vec::new()
113}
114
115#[cfg(all(test, feature = "lang-rust"))]
116mod tests {
117 use super::*;
118 use tree_sitter::Parser;
119
120 fn parse_rust(source: &str) -> tree_sitter::Tree {
121 let mut parser = Parser::new();
122 parser
123 .set_language(&tree_sitter_rust::LANGUAGE.into())
124 .expect("failed to set Rust language");
125 parser.parse(source, None).expect("failed to parse source")
126 }
127
128 #[test]
129 fn test_extract_function_name_happy_path() {
130 let source = "fn foo() {}";
132 let tree = parse_rust(source);
133 let root = tree.root_node();
134 let func_node = root.named_child(0).expect("expected child");
136 assert_eq!(func_node.kind(), "function_item");
137 let result = extract_function_name(&func_node, source, "function");
139 assert_eq!(result, Some("foo".to_string()));
141 }
142
143 #[test]
144 fn test_extract_function_name_wrong_kind() {
145 let source = "struct Bar {}";
147 let tree = parse_rust(source);
148 let root = tree.root_node();
149 let node = root.named_child(0).expect("expected child");
150 assert_eq!(node.kind(), "struct_item");
151 let result = extract_function_name(&node, source, "class");
153 assert_eq!(result, None);
155 }
156
157 #[test]
158 fn test_find_method_for_receiver_happy_path() {
159 let source = "fn bar() {}";
161 let tree = parse_rust(source);
162 let root = tree.root_node();
163 let node = root.named_child(0).expect("expected child");
164 let result = find_method_for_receiver(&node, source, None);
166 assert_eq!(result, Some("bar".to_string()));
168 }
169
170 #[test]
171 fn test_find_method_for_receiver_wrong_kind() {
172 let source = "struct Baz {}";
174 let tree = parse_rust(source);
175 let root = tree.root_node();
176 let node = root.named_child(0).expect("expected child");
177 let result = find_method_for_receiver(&node, source, None);
179 assert_eq!(result, None);
181 }
182
183 #[test]
184 fn test_find_receiver_type_happy_path() {
185 let source = "struct Foo; impl Foo { fn x() {} }";
187 let tree = parse_rust(source);
188 let root = tree.root_node();
189 let impl_node = (0..root.named_child_count())
191 .filter_map(|i| root.named_child(i as u32))
192 .find(|n| n.kind() == "impl_item")
193 .expect("expected impl_item node");
194 let result = find_receiver_type(&impl_node, source);
196 assert_eq!(result, Some("Foo".to_string()));
198 }
199
200 #[test]
201 fn test_find_receiver_type_wrong_kind() {
202 let source = "fn qux() {}";
204 let tree = parse_rust(source);
205 let root = tree.root_node();
206 let node = root.named_child(0).expect("expected child");
207 let result = find_receiver_type(&node, source);
209 assert_eq!(result, None);
211 }
212}