Skip to main content

code_analyze_core/languages/
go.rs

1use tree_sitter::Node;
2
3/// Tree-sitter query for extracting Go elements (functions, methods, and types).
4pub const ELEMENT_QUERY: &str = r"
5(function_declaration
6  name: (identifier) @func_name) @function
7(method_declaration
8  name: (field_identifier) @method_name) @function
9(type_spec
10  name: (type_identifier) @type_name
11  type: (struct_type)) @class
12(type_spec
13  name: (type_identifier) @type_name
14  type: (interface_type)) @class
15";
16
17/// Tree-sitter query for extracting function calls.
18pub const CALL_QUERY: &str = r"
19(call_expression
20  function: (identifier) @call)
21(call_expression
22  function: (selector_expression field: (field_identifier) @call))
23";
24
25/// Tree-sitter query for extracting type references.
26pub const REFERENCE_QUERY: &str = r"
27(type_identifier) @type_ref
28";
29
30/// Tree-sitter query for extracting Go imports.
31pub const IMPORT_QUERY: &str = r"
32(import_declaration) @import_path
33";
34
35/// Find method name for a receiver type.
36#[must_use]
37pub fn find_method_for_receiver(
38    node: &Node,
39    source: &str,
40    _depth: Option<usize>,
41) -> Option<String> {
42    if node.kind() != "method_declaration" && node.kind() != "function_declaration" {
43        return None;
44    }
45    node.child_by_field_name("name").and_then(|n| {
46        let start = n.start_byte();
47        let end = n.end_byte();
48        if end <= source.len() {
49            Some(source[start..end].to_string())
50        } else {
51            None
52        }
53    })
54}
55
56/// Extract inheritance information from a Go type node.
57#[must_use]
58pub fn extract_inheritance(node: &Node, source: &str) -> Vec<String> {
59    let mut inherits = Vec::new();
60
61    // Get the type field from type_spec
62    if let Some(type_field) = node.child_by_field_name("type") {
63        match type_field.kind() {
64            "struct_type" => {
65                // For struct embedding, walk children for field_declaration_list
66                for i in 0..type_field.named_child_count() {
67                    if let Some(field_list) =
68                        type_field.named_child(u32::try_from(i).unwrap_or(u32::MAX))
69                        && field_list.kind() == "field_declaration_list"
70                    {
71                        // Walk field_declaration_list for field_declaration without name
72                        for j in 0..field_list.named_child_count() {
73                            if let Some(field) =
74                                field_list.named_child(u32::try_from(j).unwrap_or(u32::MAX))
75                                && field.kind() == "field_declaration"
76                                && field.child_by_field_name("name").is_none()
77                            {
78                                // Embedded type has no name field
79                                if let Some(type_node) = field.child_by_field_name("type") {
80                                    let text =
81                                        &source[type_node.start_byte()..type_node.end_byte()];
82                                    inherits.push(text.to_string());
83                                }
84                            }
85                        }
86                    }
87                }
88            }
89            "interface_type" => {
90                // For interface embedding, walk children for type_elem
91                for i in 0..type_field.named_child_count() {
92                    if let Some(elem) = type_field.named_child(u32::try_from(i).unwrap_or(u32::MAX))
93                        && elem.kind() == "type_elem"
94                    {
95                        let text = &source[elem.start_byte()..elem.end_byte()];
96                        inherits.push(text.to_string());
97                    }
98                }
99            }
100            _ => {}
101        }
102    }
103
104    inherits
105}