Skip to main content
interlace
Plugin: maintainabilityRules

nested-complexity-hotspots

Report control structures nested deeper than a readable limit.

Report a control structure nested more than maxDepth levels deep. Deep nesting forces a reader to hold every enclosing condition in mind at once.

This rule is part of eslint-plugin-maintainability.

Quick Summary

AspectDetails
SeverityError (code quality)
Auto-Fix❌ No
CategoryQuality
Suggestions💡 Early return, guard clauses, extract method

Rule Details

A structure's depth is itself plus every control structure enclosing it: if, switch, the loops (for, for...of, for...in, while, do...while) and try. The rule reports a conditional (if, switch) or a loop whose depth exceeds maxDepth (default 4).

An else if is a link of a flat chain, not a nested level: a long if / else if / else chain sits at depth one.

Configuration

OptionTypeDefaultDescription
maxDepthnumber4Deepest nesting allowed
countConditionalsbooleantrueReport if and switch structures
countLoopsbooleantrueReport for, for...of, for...in, while and do...while loops

A kind turned off is not reported; it still adds a level to the structures nested inside it.

Examples

❌ Incorrect

function process(orders: Order[]) {
  for (const order of orders) {
    if (order.active) {
      for (const item of order.items) {
        if (item.stock > 0) {
          if (item.price > 100) {
            // depth 5
            discount(item);
          }
        }
      }
    }
  }
}

✅ Correct

function process(orders: Order[]) {
  for (const order of orders) {
    if (!order.active) continue;
    order.items.filter(isDiscountable).forEach(discount);
  }
}

// A flat chain is depth one
if (a) {
  first();
} else if (b) {
  second();
} else if (c) {
  third();
}

Configuration Examples

// eslint.config.mjs
export default [
  {
    rules: {
      'maintainability/nested-complexity-hotspots': ['error', { maxDepth: 3 }],
    },
  },
];

Further Reading

Known False Negatives

A try block as the deepest structure

Why: try adds a level to what it encloses but is neither a conditional nor a loop, so it is not reported itself.

Use this rule

npm install -D oxlint-plugin-maintainability
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-maintainability"],  "rules": {    "maintainability/nested-complexity-hotspots": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-maintainability'],    rules: {      'maintainability/nested-complexity-hotspots': 'error',    },  },});

oxlint-plugin-maintainability re-exports eslint-plugin-maintainability/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.