Code Complexity Analyzer
Measure cyclomatic complexity, cognitive complexity, nesting depth, and line count. Spot high-complexity functions before they become technical debt.
What Is Cyclomatic Complexity?
Cyclomatic complexity (CC), introduced by Thomas McCabe in 1976, counts the number of linearly independent paths through a piece of code. The metric is derived from the control flow graph: each decision point (if, else if, for, while, case, catch, &&, ||, ternary) adds 1 to the base score of 1.
A function with cyclomatic complexity of 1 has a single straight-line path. Every branch doubles potential paths. The standard thresholds are:
- 1–10 — Simple, low risk. Easy to test and understand.
- 11–20 — Moderate complexity. Consider refactoring.
- 21+ — High complexity. Very difficult to test completely. Refactor urgently.
Cyclomatic complexity directly correlates with the minimum number of test cases needed for full branch coverage. A CC of 12 means you need at least 12 test cases to cover all paths.
What Is Cognitive Complexity?
Cognitive complexity, developed by G. Ann Campbell at SonarSource (2018), measures how hard code is to understand, not just how many paths it has. Unlike cyclomatic complexity, cognitive complexity penalizes nesting more heavily — each additional level of nesting adds an extra increment to the penalty for control structures inside it.
The key differences from cyclomatic complexity:
- Nested structures are penalized with a nesting increment (depth x 1 added per control flow statement)
- Logical operators in sequences (a && b && c) count as 1, not 2
- Recursion adds a penalty of 1
- Linear jumps (break, continue with labels) add 1
A function with cognitive complexity above 15 is considered hard to read. Above 25 is considered unmaintainable by most teams.
Nesting Depth and Why It Matters
Nesting depth measures the deepest level of nested control structures in a function. Each if, for, while, try, or switch that contains another adds a level. Deep nesting is the primary driver of cognitive complexity and is one of the most common sources of bugs in production code.
A nesting depth above 4 is a strong signal to extract inner blocks into helper functions. The early-return pattern (guard clauses) and strategy/command patterns are the most effective refactoring techniques for reducing nesting.
How to Reduce Complexity
// HIGH COMPLEXITY — nesting depth 4, CC 7
function processUser(user) {
if (user) {
if (user.active) {
if (user.role === 'admin') {
if (user.permissions.length > 0) {
return user.permissions.map(p => p.name);
}
}
}
}
return [];
}
// REFACTORED — nesting depth 1, CC 4
function processUser(user) {
if (!user) return [];
if (!user.active) return [];
if (user.role !== 'admin') return [];
if (user.permissions.length === 0) return [];
return user.permissions.map(p => p.name);
}
The refactored version uses guard clauses (early returns) to eliminate nesting. This pattern is also called the "bouncer pattern" — fail fast and exit early, so the happy path remains at nesting level 0.
Frequently Asked Questions
What cyclomatic complexity score is acceptable?
For most production codebases, a cyclomatic complexity of 10 or below per function is considered acceptable. Scores of 11–20 indicate the function should be reviewed for potential refactoring. Above 20 is considered high risk — such functions are statistically associated with a much higher defect rate and are very difficult to test completely. NASA and many safety-critical coding standards cap functions at a CC of 10.
What is the difference between cyclomatic and cognitive complexity?
Cyclomatic complexity counts the number of independent execution paths through a function (useful for measuring testability). Cognitive complexity measures how difficult the code is to read and understand by penalizing nesting more severely than linear decision points. A deeply nested if-inside-for-inside-while scores higher on cognitive complexity than a flat chain of if/else statements with the same cyclomatic score, because nesting is harder for humans to mentally parse.
Does this tool parse the code with an AST?
This tool uses pattern-based analysis on the raw text rather than a full abstract syntax tree (AST) parser. It counts decision keywords (if, else if, for, while, switch case, catch, ternary, logical operators) using language-specific regex patterns. This approach works well for standard imperative code but may miss complex edge cases like multi-line ternaries or deeply interpolated expressions. For production CI integration, use ESLint's complexity rule or tools like SonarQube that perform true AST analysis.
How do I integrate complexity checking into CI/CD?
For JavaScript/TypeScript projects, add ESLint's built-in complexity rule to your .eslintrc: "complexity": ["error", 10]. For cognitive complexity, use the eslint-plugin-sonarjs plugin with the cognitive-complexity rule. For Python, tools like Radon (radon cc -n C src/) integrate with pre-commit hooks and GitHub Actions. For Java, use Checkstyle's CyclomaticComplexity check or SonarQube's cognitive complexity metric in your build pipeline.
What are the best refactoring patterns for high-complexity functions?
The most effective patterns are: (1) Guard clauses — replace nested conditionals with early returns to flatten nesting depth. (2) Extract method — pull inner blocks into well-named helper functions, each with a single responsibility. (3) Strategy pattern — replace large switch/case blocks or if-else chains with a lookup table or polymorphism. (4) Decompose conditional — extract complex boolean conditions into named functions that document intent. (5) Replace nested loops with LINQ/streams/map-filter-reduce chains, which are more declarative and readable.
Related Tools
- Regex Tester — Build and debug regular expressions with live match highlighting
- CSS Gradient Generator — Generate linear and radial gradients with live preview
- Color Contrast Checker — Test WCAG AA/AAA accessibility compliance
Built by Michael Lip. 100% client-side. No code leaves your browser.