Coverage for parsers / go.py: 74%
53 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-08 15:04 -0800
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-08 15:04 -0800
1"""Go tree-sitter parser and function collection."""
3from __future__ import annotations
5import tree_sitter_go as tsgo
6from tree_sitter import Language
8from parsers.common import parse_with_language
9from parsers.shared import create_parse, create_collect_functions
11GO_LANGUAGE = Language(tsgo.language())
13parse = create_parse(GO_LANGUAGE)
16def _collect_functions_recursive(node, acc: list) -> None:
17 if node.type in ("function_declaration", "method_declaration"):
18 acc.append(node)
19 elif node.type == "func_literal":
20 if is_named_func_literal(node):
21 acc.append(node)
22 for child in node.children:
23 _collect_functions_recursive(child, acc)
26collect_functions = create_collect_functions(_collect_functions_recursive)
29def is_named_func_literal(node) -> bool:
30 """Check if a func_literal is assigned to a variable (named closure).
32 Matches patterns like:
33 f := func() {} (short_var_declaration)
34 var f = func() {} (var_spec)
35 """
36 if node.type != "func_literal":
37 return False
38 parent = node.parent
39 if parent is None:
40 return False
41 if (
42 parent.type == "expression_list"
43 and parent.parent
44 and parent.parent.type == "short_var_declaration"
45 ):
46 return True
47 if parent.type == "var_spec":
48 return True
49 return False
52def func_name(node) -> str:
53 """Extract function name from a function node."""
54 if node.type in ("function_declaration", "method_declaration"):
55 name_node = node.child_by_field_name("name")
56 if name_node:
57 return name_node.text.decode()
58 return "<anonymous>"
59 if node.type == "func_literal":
60 parent = node.parent
61 if parent is None:
62 return "<anonymous>"
63 if (
64 parent.type == "expression_list"
65 and parent.parent
66 and parent.parent.type == "short_var_declaration"
67 ):
68 svd = parent.parent
69 left = svd.child_by_field_name("left")
70 if left:
71 for child in left.children:
72 if child.type == "identifier":
73 return child.text.decode()
74 if parent.type == "var_spec":
75 name_node = parent.child_by_field_name("name")
76 if name_node:
77 return name_node.text.decode()
78 for child in parent.children:
79 if child.type == "identifier":
80 return child.text.decode()
81 return "<anonymous>"
82 return "<anonymous>"