Skip to main content

code_analyze_mcp/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.
36pub fn find_method_for_receiver(
37    node: &Node,
38    source: &str,
39    _depth: Option<usize>,
40) -> Option<String> {
41    if node.kind() != "method_declaration" && node.kind() != "function_declaration" {
42        return None;
43    }
44    node.child_by_field_name("name").and_then(|n| {
45        let start = n.start_byte();
46        let end = n.end_byte();
47        if end <= source.len() {
48            Some(source[start..end].to_string())
49        } else {
50            None
51        }
52    })
53}
54
55/// Extract inheritance information from a Go type node.
56pub fn extract_inheritance(node: &Node, source: &str) -> Vec<String> {
57    let mut inherits = Vec::new();
58
59    // Get the type field from type_spec
60    if let Some(type_field) = node.child_by_field_name("type") {
61        match type_field.kind() {
62            "struct_type" => {
63                // For struct embedding, walk children for field_declaration_list
64                for i in 0..type_field.named_child_count() {
65                    if let Some(field_list) = type_field.named_child(i as u32)
66                        && field_list.kind() == "field_declaration_list"
67                    {
68                        // Walk field_declaration_list for field_declaration without name
69                        for j in 0..field_list.named_child_count() {
70                            if let Some(field) = field_list.named_child(j as u32)
71                                && field.kind() == "field_declaration"
72                                && field.child_by_field_name("name").is_none()
73                            {
74                                // Embedded type has no name field
75                                if let Some(type_node) = field.child_by_field_name("type") {
76                                    let text =
77                                        &source[type_node.start_byte()..type_node.end_byte()];
78                                    inherits.push(text.to_string());
79                                }
80                            }
81                        }
82                    }
83                }
84            }
85            "interface_type" => {
86                // For interface embedding, walk children for type_elem
87                for i in 0..type_field.named_child_count() {
88                    if let Some(elem) = type_field.named_child(i as u32)
89                        && elem.kind() == "type_elem"
90                    {
91                        let text = &source[elem.start_byte()..elem.end_byte()];
92                        inherits.push(text.to_string());
93                    }
94                }
95            }
96            _ => {}
97        }
98    }
99
100    inherits
101}