Coverage for parsers / go.py: 74%

53 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-08 15:04 -0800

1"""Go tree-sitter parser and function collection.""" 

2 

3from __future__ import annotations 

4 

5import tree_sitter_go as tsgo 

6from tree_sitter import Language 

7 

8from parsers.common import parse_with_language 

9from parsers.shared import create_parse, create_collect_functions 

10 

11GO_LANGUAGE = Language(tsgo.language()) 

12 

13parse = create_parse(GO_LANGUAGE) 

14 

15 

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) 

24 

25 

26collect_functions = create_collect_functions(_collect_functions_recursive) 

27 

28 

29def is_named_func_literal(node) -> bool: 

30 """Check if a func_literal is assigned to a variable (named closure). 

31 

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 

50 

51 

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>"