cognitive_complexity 0.2.0
cognitive_complexity: ^0.2.0 copied to clipboard
Algorithmic Cognitive Complexity calculation library and CLI tool for Dart and Flutter.
A deterministic, zero-token Cognitive Complexity calculation library, CLI tool, and GitHub Action for Dart and Flutter repositories.
Unlike Cyclomatic Complexity (which measures control flow branch density), Cognitive Complexity measures how difficult a method is for a human engineer to read and understand, following the whitepaper specification by G. Ann Campbell.
Features #
- Modern Dart 3 AST Support: Natively parses switch expressions, pattern
guards (
whenclauses), and collection control flow structures. - Deterministic Engine: Calculates complexity algorithmically without invoking LLM calls or external network requests.
- Git Diff Analysis: Compares current workspace declarations against a target base ref to isolate complexity deltas (Δ) in modified functions.
- Lightweight GitHub Action: Exposes workflow annotations and step summaries for CI check integration.
Scoring Model #
Scores follow the SonarSource Cognitive Complexity whitepaper (G. Ann Campbell, v1.7):
- Structural (+1, plus current nesting depth):
if, the conditional (?:) operator,switchstatements and expressions,for(includingfor-inandawait for),while,do-while, andcatch. Each also deepens nesting for its contents. - Hybrid (flat +1, no nesting penalty):
elseandelse if. Anelse ifchain does not deepen nesting — contents of every branch sit one level below the headif. - Fundamental (flat +1): each sequence of like logical operators
(
a && b && cis +1) with +1 for each alternation between&&and||, and labeledbreak/continue. - Nesting only (+0): lambdas and local function declarations deepen nesting for their contents but add nothing themselves.
- Free (+0):
try/finally,throw/rethrow, earlyreturn, unlabeledbreak/continue, null-aware operators (??,??=,?.),assert, andswitchcase labels.
Dart-specific interpretations of the spec:
- Pattern
whenguards add +1 (a guard is an extra condition to evaluate). - Pattern-level combinators (
case 1 || 2:,case > 0 && < 10) are free — an or-pattern is the modern spelling of stacked case labels, which the spec scores at zero. - The whitepaper's "+1 for each method in a recursion cycle" is not implemented, matching SonarSource's own reference implementation (sonar-java), which omits it as well.
💻 CLI Usage #
You can run the scanner on-demand without installation, locally inside a project, or globally.
On-Demand (Recommended) #
Run the scanner directly in any Dart or Flutter project root using the Dart SDK:
dart run cognitive_complexity@ [options] [targets]
(Note: The trailing @ instructs the Dart VM to resolve and execute the latest published version of the package on-demand).
Project Dependency #
Add the package to your dev_dependencies in pubspec.yaml:
dev_dependencies:
cognitive_complexity: ^0.2.0
And run:
dart run cognitive_complexity [options] [targets]
Global Installation #
To install the scanner globally on your system:
dart install cognitive_complexity
cognitive_complexity [options] [targets]
Options #
-t, --threshold <value>: Minimum score to display in the terminal (default:0).-f, --fail-threshold <value>: Ceilings score. Exits with code1if any declaration exceeds this value.-d, --git-diff <git-ref>: Compares current code against a git commit/ref, evaluating complexity deltas (Δ) on modified functions.--fail-on-increase: When using--git-diff, exits with code1if any modified function experienced a complexity score increase.--format <text|json|github>: Report output formatting (default:text).
📦 Library API Usage #
Exposes programmatic analyzers for Dart and Flutter applications.
Add to pubspec.yaml:
dependencies:
cognitive_complexity: ^0.2.0
Programmatic Scan Example #
import 'package:cognitive_complexity/cognitive_complexity.dart';
void main() {
final analyzer = ComplexityAnalyzer();
// Scan a directory or file path
final results = analyzer.analyzePath('lib/src');
for (final res in results) {
print('${res.name}: score is ${res.score} (${res.filePath}:L${res.startLine})');
}
}
🤖 GitHub Actions Integration #
You can run complexity checks automatically on pull requests using the integrated composite GitHub Action.
PR Delta Audit Workflow Example #
This workflow scans only the files and functions modified in the pull request. It injects inline code review warnings directly on modified PR lines and prints a beautiful markdown transition table to the workflow summary.
Create .github/workflows/complexity.yml:
name: Cognitive Complexity Audit
on:
pull_request:
branches: [ main ]
jobs:
audit:
runs-on: ubuntu-latest
permissions:
pull-requests: write # Required to post/update sticky PR comments
contents: read # Required for actions/checkout
steps:
- name: Checkout Repository
uses: actions/checkout@v7
with:
# Fetch full history so merge-base comparison can locate common ancestor
fetch-depth: 0
- name: Setup Dart SDK
uses: dart-lang/setup-dart@v1
- name: Run Complexity Scanner
uses: kevmoo/cognitive_complexity.dart@main
with:
# Auto-configures pull request merge base comparison
diff-base: origin/${{ github.base_ref }}
fail-threshold: 15
fail-on-increase: true
Action Configuration Parameters (with:) #
targets: Space-separated directories or files to scan (default:lib).threshold: Minimum score to include in report tables (default:0).fail-threshold: Max complexity ceiling (default:15).diff-base: Git ref to compare against (e.g.origin/main). Leave empty to compare full repository files.fail-on-increase: Settrueto block PR merge if complexity increases.format: Summary format:github(GHA annotations + summary),text, orjson.
Permissions & Security #
By default, GitHub Actions runs with read-only permissions. To enable posting and updating the sticky PR comment summary directly on the PR thread, you must explicitly grant write permissions to pull-requests:
permissions:
pull-requests: write
contents: read
If write permissions are not granted, the scanner will execute normally, and output annotations and step summaries, but will skip posting the PR comment without failing the build.
Fork PR Security Note
Workflows triggered by pull requests from external forks are executed with restricted read-only permissions by GitHub. For security reasons, the action will gracefully skip posting PR comments on forks to prevent Remote Code Execution (RCE) risks, while still validating code complexity in GHA annotations and build status.