Long, complex functions are hard for humans (and AI agents) to understand. Asking an agent to "refactor the code to make it cleaner" is poorly defined and leaves the agent to make arbitrary decisions.

This Dart package, GitHub Action, and AI agent skill make finding and fixing overly complex logic easy, reliable, and repeatable by implementing the Cognitive Complexity principles articulated by SonarSource.

✨ Features

  • Modern Dart 3 AST Support: Natively parses switch expressions, pattern guards (when clauses), and collection control flow structures.
  • Deterministic Engine: Calculates complexity algorithmically without LLM calls, external network requests, or token latency.
  • Statement Data-Flow Analysis: Evaluates variable inputs, mutations, and downstream live outputs for arbitrary statement slices to power automated method extraction.
  • Git Diff Analysis & Ratchet: Compares working copy changes against a target base ref to isolate complexity deltas (Ξ”) in modified functions.
  • Lightweight GitHub Action: Exposes workflow annotations and markdown summary tables for automated CI quality gates.

⚑ Quick Start

CLI (On-Demand)

Run the scanner directly in any Dart or Flutter project without prior installation:

dart run cognitive_complexity@

(Requires Dart SDK 3.12.0 or greater).

cognitive_complexity CLI Options

$ cognitive_complexity --help
Dart & Flutter Cognitive Complexity Calculator

Usage: dart run cognitive_complexity [options] [<file_or_directory>...]

Without targets, scans lib/ (or every workspace member and packages/*/lib, pkgs/*/lib in monorepos).

Options:
-h, --help                          Print this usage information.
-t, --threshold                     Minimum complexity score to include in output.
                                    (defaults to "0")
-f, --fail-threshold                Exit with non-zero code if any function score exceeds this value.
    --max-file-lines=<lines>        Opt-in maximum physical line count per source file (0 = disabled). Exits with non-zero code when exceeded.
    --max-function-lines=<lines>    Opt-in maximum line span per function/method declaration (0 = disabled). Exits with non-zero code when exceeded.
-d, --git-diff=<git-ref>            Git reference to compare against. Only evaluates modified files and function complexity deltas.
    --fail-on-increase              When using --git-diff, exit with non-zero code if any function increased in complexity. When --fail-threshold is also set, only increases that exceed the threshold fail.
    --format                        Output format.
                                    [text (default), json, github]
    --comment-output=<path>         With --format=github, also write a standalone report to this path, ordered by significance and capped by --max-comment-rows. Intended for posting as a PR comment while the step summary keeps the full table.
    --max-comment-rows=<count>      Maximum table rows in --comment-output (0 = unlimited). GitHub rejects comment bodies over 65536 characters.
                                    (defaults to "0")
    --exclude=<glob>                Glob patterns of files/directories to exclude (repeatable or comma-separated).
    --[no-]ignore-generated         Exclude generated files (*.g.dart, *.freezed.dart, *.mocks.dart, etc.).
                                    (defaults to on)

data_flow CLI Options

$ data_flow --help
Dart Data-Flow & Method Extraction Analyzer

Analyzes a target slice of code inside a Dart function and deterministically
calculates required parameters (inputs), modified variables (mutations),
and live return values (outputs) for safe method extraction.

Usage: dart run cognitive_complexity:data_flow [options] <file.dart[:start-end]>

Examples:
  # Analyze lines 45 through 80 of auth.dart (Agent-first JSON default)
  dart run cognitive_complexity:data_flow lib/src/auth.dart:45-80

  # Analyze with explicit flags and custom helper name
  dart run cognitive_complexity:data_flow --lines=45-80 --name=_validateToken lib/src/auth.dart

  # Human-readable terminal output
  dart run cognitive_complexity:data_flow --format=text lib/src/auth.dart:45-80

Options:
-h, --help        Print this usage information.
-l, --lines       Target 1-based line range of the code block to extract (e.g. 45-80).
-n, --name        Name for the proposed extracted helper function.
                  (defaults to "_extracted")
-f, --format      Output format.
                  [json (default), text]
    --sdk-path    Path to the Dart SDK root used for analysis. Defaults to auto-discovery (running VM, DART_SDK environment variable, PATH, FLUTTER_ROOT).

file_split CLI Options

$ file_split --help
Dart File Decomposition & Acyclic Dependency Cut Advisor (file_split)

Usage: dart run cognitive_complexity:file_split [options] <file_or_dir>...

Options:
-h, --help                         Print this usage information.
    --target-lines=<lines>         Target maximum line count per extracted file cluster.
                                   (defaults to "800")
    --min-cluster-lines=<lines>    Minimum line count for a standalone extracted cluster (prevents micro-fragmentation).
                                   (defaults to "40")
    --[no-]use-parts               Allow or prefer `part` / `part of` directives when decomposing oversized classes or tightly coupled SCCs (defaults to auto-detect with user confirmation prompt).
    --format                       Output format (text or json).
                                   [text (default), json]
    --sdk-path                     Path to the Dart SDK root (overrides auto-discovery).

shallow CLI Options

$ shallow --help
Dart Single-Caller Shallow Helper & Inlining Advisor (shallow)

Detects single-caller pass-through helpers, parameter clumps, and micro-helpers,
and simulates exact caller Cognitive Complexity after re-inlining.

Usage: dart run cognitive_complexity:shallow [options] [file_or_directory...]

Options:
-h, --help                     Print this usage information.
    --max-caller-cc=<score>    Maximum allowed caller Cognitive Complexity score after inlining for a candidate to be classified as SAFE_INLINE.
                               (defaults to "15")
    --max-params=<count>       Parameter count threshold at or above which a single-caller function is flagged as HIGH_ARITY.
                               (defaults to "5")
    --only-safe                Only output SAFE_INLINE candidates where inlining keeps caller complexity <= --max-caller-cc.
-d, --git-diff=<git-ref>       Git reference to compare against. Only reports shallow helpers in modified files.
    --fail-on-safe-inline      Exit with non-zero code if any SAFE_INLINE single-caller shallow helper is found.
    --format                   Output format (text or json).
                               [text (default), json]
    --exclude=<glob>           Glob patterns of files/directories to exclude (repeatable or comma-separated).
    --[no-]ignore-generated    Exclude generated files (*.g.dart, *.freezed.dart, *.mocks.dart, etc.).
                               (defaults to on)

Library API

Add cognitive_complexity to your pubspec.yaml:

import 'package:cognitive_complexity/cognitive_complexity.dart';

void main() {
  final analyzer = ComplexityAnalyzer();
  final results = analyzer.analyzePath('lib');

  for (final res in results) {
    print('${res.name}: score is ${res.score} (${res.filePath}:L${res.startLine})');
  }
}

Suppressing Findings

Use comment directives (shared across package:analytica tools) to suppress complexity or line-limit checks for irreducible state machines, generated lookup tables, or individual functions:

  • File-level suppression: Place // cognitive_complexity:ignore_for_file anywhere in the file.
  • Declaration-level suppression: Place // cognitive_complexity:ignore on the line immediately preceding a function, method, or constructor.

GitHub Actions

Add automated complexity audits to .github/workflows/complexity.yml:

name: Cognitive Complexity Audit

on:
  pull_request:
    branches: [main]

jobs:
  audit:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write # Required for sticky PR comment summaries
      contents: read
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v7
        with:
          fetch-depth: 0 # Full history required for diff-base merge-base comparison

      - name: Setup Dart SDK
        uses: dart-lang/setup-dart@v1

      - name: Run Complexity Scanner
        uses: kevmoo/analytica.dart/packages/cognitive_complexity@main
        with:
          diff-base: origin/${{ github.base_ref }}
          fail-threshold: 15
          fail-on-increase: true

Action Inputs Reference

Input Default Description
targets Auto Directories or files to scan. Auto-discovers lib/ or workspace package libs.
threshold 0 Minimum score required to include a declaration in summary tables.
fail-threshold 15 Maximum complexity ceiling allowed before failing the build.
max-file-lines 0 Opt-in maximum physical line count per source file (0 = disabled).
max-function-lines 0 Opt-in maximum line span per function/method declaration (0 = disabled).
diff-base Auto Git ref to compare against (e.g. origin/main). Auto-detects PR base.
fail-on-increase false When true, blocks PR merge on complexity increases exceeding fail-threshold.
format github Output format: github (annotations + step summary), text, or json.
max-comment-rows 0 Maximum table rows in the sticky PR comment (0 = unlimited).

🧠 AI Agent Integration

This repository packages an agent skill (dart-cognitive-complexity) to train AI pair programmers on Cognitive Complexity scoring and refactoring patterns:

Install using either the dart skills CLI:

dart run skills@ add kevmoo/analytica.dart --skill dart-cognitive-complexity

Or npx skills:

npx skills add kevmoo/analytica.dart --skill dart-cognitive-complexity

πŸ“š Documentation & Guides

Explore in-depth documentation in the doc/ directory:

Libraries

cognitive_complexity
A deterministic, algorithmic Cognitive Complexity calculation library and CLI tool for Dart and Flutter.
data_flow
A deterministic semantic data-flow analysis library and CLI tool for Dart.