Coverage for metrics / cyclomatic / shared.py: 100%
18 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"""Shared cyclomatic complexity logic for all languages."""
3from __future__ import annotations
6def create_cyclomatic_computer(skip_check_fn, decision_types, logical_ops=None):
7 """Factory to create language-specific cyclomatic complexity computer.
9 Args:
10 skip_check_fn: Function(node, top_func) -> bool that returns True to skip recursion into a node
11 decision_types: Set/SetList of node types that add 1 to complexity
12 logical_ops: Optional set of token types that count as logical operators (for &&/??)
13 """
15 def _count_decisions(node, top_func) -> int:
16 """Recursively count decision points in an AST subtree."""
17 count = 0
19 for child in node.children:
20 if skip_check_fn(child, top_func):
21 continue
23 if child.type in decision_types:
24 count += 1
25 elif logical_ops and child.type == "binary_expression":
26 count += sum(1 for sub in child.children if sub.type in logical_ops)
28 count += _count_decisions(child, top_func)
30 return count
32 return _count_decisions
35def create_cyclomatic_wrapper(count_decisions_fn):
36 """Create compute_cyclomatic function wrapper."""
38 def compute_cyclomatic(func_node) -> int:
39 """Compute McCabe cyclomatic complexity for a function node.
41 CC = 1 + number of decision points.
42 """
43 return 1 + count_decisions_fn(func_node, top_func=func_node)
45 return compute_cyclomatic