Coverage for metrics / halstead / common.py: 100%

28 statements  

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

1"""Shared Halstead collection logic for all languages.""" 

2 

3from __future__ import annotations 

4 

5from common import compute_halstead 

6from functools import partial 

7from models import HalsteadMetrics 

8 

9 

10def _collect_halstead_generic( 

11 node, 

12 operators, 

13 operands, 

14 comment_types, 

15 keyword_operators, 

16 operand_types, 

17 operator_tokens, 

18) -> None: 

19 """Recursively classify AST nodes as operators or operands. 

20 

21 Language-specific behavior is controlled entirely by the constant sets: 

22 *comment_types*, *keyword_operators*, *operand_types*, *operator_tokens*. 

23 """ 

24 if node.type in comment_types: 

25 return 

26 

27 if node.type in keyword_operators: 

28 operators.append(node.type) 

29 for child in node.children: 

30 _collect_halstead_generic( 

31 child, 

32 operators, 

33 operands, 

34 comment_types, 

35 keyword_operators, 

36 operand_types, 

37 operator_tokens, 

38 ) 

39 return 

40 

41 if node.child_count == 0: 

42 text = node.text.decode() 

43 if node.type in operand_types: 

44 operands.append(text) 

45 elif text in operator_tokens or node.type in operator_tokens: 

46 operators.append(text) 

47 return 

48 

49 for child in node.children: 

50 _collect_halstead_generic( 

51 child, 

52 operators, 

53 operands, 

54 comment_types, 

55 keyword_operators, 

56 operand_types, 

57 operator_tokens, 

58 ) 

59 

60 

61def compute_halstead_generic( 

62 root, comment_types, keyword_operators, operand_types, operator_tokens 

63) -> HalsteadMetrics: 

64 """Compute Halstead metrics for an AST using the given language token sets.""" 

65 operators: list[str] = [] 

66 operands: list[str] = [] 

67 _collect_halstead_generic( 

68 root, 

69 operators, 

70 operands, 

71 comment_types, 

72 keyword_operators, 

73 operand_types, 

74 operator_tokens, 

75 ) 

76 return compute_halstead(operators, operands) 

77 

78 

79def make_compute_halstead( 

80 comment_types, keyword_operators, operand_types, operator_tokens 

81): 

82 return partial( 

83 compute_halstead_generic, 

84 comment_types=comment_types, 

85 keyword_operators=keyword_operators, 

86 operand_types=operand_types, 

87 operator_tokens=operator_tokens, 

88 )