code_analyze_core/languages/
go.rs1use tree_sitter::Node;
4
5pub const ELEMENT_QUERY: &str = r"
7(function_declaration
8 name: (identifier) @func_name) @function
9(method_declaration
10 name: (field_identifier) @method_name) @function
11(type_spec
12 name: (type_identifier) @type_name
13 type: (struct_type)) @class
14(type_spec
15 name: (type_identifier) @type_name
16 type: (interface_type)) @class
17";
18
19pub const CALL_QUERY: &str = r"
21(call_expression
22 function: (identifier) @call)
23(call_expression
24 function: (selector_expression field: (field_identifier) @call))
25";
26
27pub const REFERENCE_QUERY: &str = r"
29(type_identifier) @type_ref
30";
31
32pub const IMPORT_QUERY: &str = r"
34(import_declaration) @import_path
35";
36
37#[must_use]
39pub fn find_method_for_receiver(
40 node: &Node,
41 source: &str,
42 _depth: Option<usize>,
43) -> Option<String> {
44 if node.kind() != "method_declaration" && node.kind() != "function_declaration" {
45 return None;
46 }
47 node.child_by_field_name("name").and_then(|n| {
48 let start = n.start_byte();
49 let end = n.end_byte();
50 if end <= source.len() {
51 Some(source[start..end].to_string())
52 } else {
53 None
54 }
55 })
56}
57
58#[must_use]
60pub fn extract_inheritance(node: &Node, source: &str) -> Vec<String> {
61 let mut inherits = Vec::new();
62
63 if let Some(type_field) = node.child_by_field_name("type") {
65 match type_field.kind() {
66 "struct_type" => {
67 for i in 0..type_field.named_child_count() {
69 if let Some(field_list) =
70 type_field.named_child(u32::try_from(i).unwrap_or(u32::MAX))
71 && field_list.kind() == "field_declaration_list"
72 {
73 for j in 0..field_list.named_child_count() {
75 if let Some(field) =
76 field_list.named_child(u32::try_from(j).unwrap_or(u32::MAX))
77 && field.kind() == "field_declaration"
78 && field.child_by_field_name("name").is_none()
79 {
80 if let Some(type_node) = field.child_by_field_name("type") {
82 let text =
83 &source[type_node.start_byte()..type_node.end_byte()];
84 inherits.push(text.to_string());
85 }
86 }
87 }
88 }
89 }
90 }
91 "interface_type" => {
92 for i in 0..type_field.named_child_count() {
94 if let Some(elem) = type_field.named_child(u32::try_from(i).unwrap_or(u32::MAX))
95 && elem.kind() == "type_elem"
96 {
97 let text = &source[elem.start_byte()..elem.end_byte()];
98 inherits.push(text.to_string());
99 }
100 }
101 }
102 _ => {}
103 }
104 }
105
106 inherits
107}
108
109#[cfg(all(test, feature = "lang-go"))]
110mod tests {
111 use super::*;
112 use tree_sitter::Parser;
113
114 fn parse_go(source: &str) -> tree_sitter::Tree {
115 let mut parser = Parser::new();
116 parser
117 .set_language(&tree_sitter_go::LANGUAGE.into())
118 .expect("failed to set Go language");
119 parser.parse(source, None).expect("failed to parse source")
120 }
121
122 #[test]
123 fn test_extract_inheritance_struct_no_embeds() {
124 let source = "package p\ntype Foo struct { x int }";
126 let tree = parse_go(source);
127 let root = tree.root_node();
128 let type_spec = (0..root.named_child_count())
130 .filter_map(|i| root.named_child(i as u32))
131 .find_map(|n| {
132 if n.kind() == "type_declaration" {
133 (0..n.named_child_count())
134 .filter_map(|j| n.named_child(j as u32))
135 .find(|c| c.kind() == "type_spec")
136 } else {
137 None
138 }
139 })
140 .expect("expected type_spec node");
141 let result = extract_inheritance(&type_spec, source);
143 assert!(
145 result.is_empty(),
146 "expected no inherited types, got {:?}",
147 result
148 );
149 }
150
151 #[test]
152 fn test_find_method_for_receiver_wrong_kind() {
153 let source = "package p\ntype Bar struct {}";
155 let tree = parse_go(source);
156 let root = tree.root_node();
157 let node = root.named_child(0).expect("expected child");
158 let result = find_method_for_receiver(&node, source, None);
160 assert_eq!(result, None);
162 }
163}