Skip to content

Complexity

complexity

Node complexity rule — the ESLint pendant of :class:ComplexityRule.

Ports the intent of QUALITY_COMPLEXITY (cc < 10, cog < 15 — the SonarSource 2025 thresholds the Python rule also uses) to TypeScript. Both metrics come from a single eslint --format json run, filtered by ruleId:

  • complexity (ESLint core) → cyclomatic
  • sonarjs/cognitive-complexity (eslint-plugin-sonarjs) → cognitive

The project's ESLint config must enable both at the AXM thresholds; this rule scores whatever the configured ESLint reports, so the thresholds live in the project's eslint.config.js (the scaffolded template wires them up).

NodeComplexityRule

Bases: NodeToolRule

Score cyclomatic + cognitive complexity findings from ESLint.

Scoring: 100 - violations * 10, min 0 — identical to the Python rule.

Source code in packages/axm-audit/src/axm_audit/core/rules/node/complexity.py
Python
@register_rule("complexity", framework=Framework.NODE)
class NodeComplexityRule(NodeToolRule):
    """Score cyclomatic + cognitive complexity findings from ESLint.

    Scoring: ``100 - violations * 10``, min 0 — identical to the Python rule.
    """

    binary = "eslint"
    install_hint = (
        "Install ESLint + sonarjs: npm install -D eslint eslint-plugin-sonarjs"
    )

    @property
    def rule_id(self) -> str:
        """Unique identifier (shared with the Python complexity rule)."""
        return "QUALITY_COMPLEXITY"

    @property
    def args(self) -> list[str]:
        """Run ESLint over the project with the JSON formatter."""
        return ["--format", "json", "."]

    def score_output(self, parsed: object, project_path: Path) -> CheckResult:
        """Score by the count of complexity-rule violations."""
        count = _count_complexity_messages(parsed) if isinstance(parsed, list) else 0
        score = max(0, 100 - count * _PENALTY)
        passed = score >= PASS_THRESHOLD
        return CheckResult(
            rule_id=self.rule_id,
            passed=passed,
            message=f"Complexity score: {score}/100 ({count} over threshold)",
            severity=Severity.WARNING if not passed else Severity.INFO,
            score=score,
            details={"violation_count": count},
            fix_hint=("Refactor functions above cc<10 / cog<15" if count > 0 else None),
        )
args property

Run ESLint over the project with the JSON formatter.

rule_id property

Unique identifier (shared with the Python complexity rule).

score_output(parsed, project_path)

Score by the count of complexity-rule violations.

Source code in packages/axm-audit/src/axm_audit/core/rules/node/complexity.py
Python
def score_output(self, parsed: object, project_path: Path) -> CheckResult:
    """Score by the count of complexity-rule violations."""
    count = _count_complexity_messages(parsed) if isinstance(parsed, list) else 0
    score = max(0, 100 - count * _PENALTY)
    passed = score >= PASS_THRESHOLD
    return CheckResult(
        rule_id=self.rule_id,
        passed=passed,
        message=f"Complexity score: {score}/100 ({count} over threshold)",
        severity=Severity.WARNING if not passed else Severity.INFO,
        score=score,
        details={"violation_count": count},
        fix_hint=("Refactor functions above cc<10 / cog<15" if count > 0 else None),
    )