Coverage for metrics / dtd / go.py: 85%

39 statements  

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

1"""Data Transformation Density (DTD) for Go.""" 

2 

3from __future__ import annotations 

4 

5from parsers.go import is_named_func_literal 

6 

7_GO_DTD_MAP_NAMES = {"Map", "Filter", "Reduce"} 

8 

9 

10def compute_dtd_go(func_node) -> int: 

11 """Compute Data Transformation Density for a Go function node.""" 

12 body = func_node.child_by_field_name("body") 

13 if body and body.type == "block": 

14 return _dtd_walk_go(body, depth=0, top_func=func_node) 

15 for child in func_node.children: 

16 if child.type == "block": 

17 return _dtd_walk_go(child, depth=0, top_func=func_node) 

18 return 0 

19 

20 

21def _is_map_call_go(node) -> bool: 

22 """Check if a call_expression is a Map/Filter/Reduce call.""" 

23 if node.type != "call_expression": 

24 return False 

25 func = node.child_by_field_name("function") 

26 if func and func.type == "selector_expression": 

27 field = func.child_by_field_name("field") 

28 if field and field.text.decode() in _GO_DTD_MAP_NAMES: 

29 return True 

30 return False 

31 

32 

33_GO_DTD_NESTED_FUNCS = {"function_declaration", "method_declaration"} 

34_GO_DTD_LITERAL_ELEMENTS = {"keyed_element", "literal_element"} 

35 

36 

37def _dtd_walk_go(node, depth: int, top_func) -> int: 

38 """Walk AST and accumulate DTD score.""" 

39 total = 0 

40 is_literal = node.type == "literal_value" 

41 for child in node.children: 

42 if child.type in _GO_DTD_NESTED_FUNCS and child is not top_func: 

43 continue 

44 if child.type == "func_literal" and child is not top_func: 

45 if not is_named_func_literal(child): 

46 total += _dtd_walk_go(child, depth, top_func) 

47 continue 

48 

49 if child.type == "literal_value" or _is_map_call_go(child): 

50 total += _dtd_walk_go(child, depth + 1, top_func) 

51 continue 

52 

53 if is_literal and child.type in _GO_DTD_LITERAL_ELEMENTS: 

54 total += depth 

55 

56 total += _dtd_walk_go(child, depth, top_func) 

57 

58 return total