Skip to content

itaymendel/oxlint-plugin-complexity

Repository files navigation

oxlint-plugin-complexity

Cyclomatic and cognitive complexity rules for oxlint with actionable error messages. Also available as a standalone library for programmatic complexity analysis.

Features:

  • Cyclomatic and cognitive complexity analysis.
  • Actionable error messages with complexity breakdown.
  • Programmatic API for custom tooling
  • Framework support: React, Vue, Angular, Svelte, Astro, Solid, Qwik
  • File types: .js .mjs .cjs .ts .tsx .jsx .vue .svelte .astro

Note: Refactoring tips require cognitive complexity (only it tracks nesting depth).

Quick Start

npm install oxlint-plugin-complexity --save-dev
// .oxlintrc.json
{
  "jsPlugins": ["oxlint-plugin-complexity"],
  "rules": {
    "complexity/complexity": [
      "error",
      {
        "cyclomatic": 20,
        "cognitive": 15
      }
    ]
  }
}

Actionable Error Messages

Error messages show a summary, line-by-line breakdown, and refactoring tips for deep nesting:

complexity(complexity): Function 'processData' has Cognitive Complexity of 15.
Maximum allowed is 10. [if: +14, for: +1]

Breakdown:
   Line 2: +1 for 'for'
   Line 3: +2 for 'if' (incl. +1 nesting)
   Line 4: +3 for 'if' (incl. +2 nesting)
   Line 5: +4 for 'if' (incl. +3 nesting)
>>> Line 6: +5 for 'if' (incl. +4 nesting) [top offender]
    ↳ Tip: Extract inner loops into helper functions - each extraction removes one nesting level
function processData(items, mode, config) {
  for (const item of items) {
    // Line 2: +1
    if (item.active) {
      // Line 3: +2 (nesting=1)
      if (mode === 'strict') {
        // Line 4: +3 (nesting=2)
        if (config.validate) {
          // Line 5: +4 (nesting=3)
          if (item.required) {
            // Line 6: +5 (nesting=4) <- top offender
          }
        }
      }
    }
  }
}

Rule Configuration

{
  "complexity/complexity": [
    "error",
    {
      // Complexity thresholds
      "cyclomatic": 20, // Default: 20
      "cognitive": 15, // Default: 15

      // Performance optimization (optional)
      "minLines": 10, // Default: 10 (skip functions <10 lines like getters; 0 = analyze all; counts comments/blanks)

      // Extraction suggestions (optional)
      "enableExtraction": true, // Default: true
      "extractionMultiplier": 1.5, // Default: 1.5 (triggers at 1.5× cognitive threshold)
      "minExtractionPercentage": 30, // Default: 30 (min % of total complexity to suggest)

      // Refactoring tip thresholds (optional, set to 0 to disable)
      "nestingTipThreshold": 3, // Default: 3
      "elseIfChainThreshold": 4, // Default: 4
      "logicalOperatorThreshold": 3, // Default: 3
    },
  ],
}

Cyclomatic Complexity

Counts decision points in code. Learn more

+1 for: if, for, for...in, for...of, while, do...while, case, catch, ? :, &&, ||, ??

Cognitive Complexity

Measures how difficult code is to understand by penalizing nesting. Learn more

  • +1 for: if/for/while/switch/catch/? : (+nesting), else, logical sequence changes, nested functions, recursion
  • Excluded: React components (PascalCase + returns JSX), default value patterns (a || [])

Refactoring Tips

Detects common complexity patterns and provides actionable tips:

  • Deep nesting (nestingTipThreshold): Suggests extracting inner loops/conditions
  • Long else-if chains (elseIfChainThreshold): Recommends lookup tables or strategy pattern
  • Logical operator sequences (logicalOperatorThreshold): Suggests extracting boolean expressions

Extraction Suggestions

Analyzes variable flow to identify extractable code blocks (enabled by default, disable with enableExtraction: false):

Example output:

Smart extraction suggestions:

  Lines 9-22: Extractable with some refactoring
    Complexity: +11 (55% of total)
    Inputs: order, config, processedItems
    Suggested: processOrder(order, config, processedItems): void

  Lines 25-33: Requires significant refactoring
    Complexity: +6 (30% of total)
    Inputs: config, totalCount, processedItems
    Issue: Mutates external variable 'totalCount' (line 27)
    Suggestion: Consider returning 'totalCount' instead of mutating it

TypeScript support: Preserves type annotations in suggested signatures:

Inputs: config: Config, results: number[]
Suggested: processBlock(config: Config, results: number[]): void

Known Limitations

Extraction suggestions use static analysis heuristics and may miss:

  • Globals/module variables (not tracked by variable flow analysis)
  • Complex flows (closures, dynamic properties, indirect mutations)

Always review suggestions before applying, even when marked "high confidence".


Migration from v0.x

Replace the removed max-cyclomatic / max-cognitive rules with the combined complexity rule:

// .oxlintrc.json
{
  "jsPlugins": ["oxlint-plugin-complexity"],
  "rules": {
-   "complexity/max-cyclomatic": ["error", { "max": 20 }],
-   "complexity/max-cognitive": ["error", { "max": 15 }]
+   "complexity/complexity": ["error", {
+     "cyclomatic": 20,
+     "cognitive": 15
+   }]
  }
}

Attribution

The cognitive complexity metric is based on G. Ann Campbell's specification (SonarSource, 2016).

License

MIT

About

Cyclomatic and cognitive complexity rules for oxlint with actionable error messages. Also available as a standalone library for programmatic complexity analysis.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors