User Rating 0.0
Total Usage 0 times
Paste code and click Analyze
Is this tool helpful?

Your feedback helps us improve.

About

Cyclomatic complexity, introduced by Thomas McCabe in 1976, quantifies the number of linearly independent paths through a program's control flow graph. The metric is computed as M = E N + 2P, where E is edge count, N is node count, and P is the number of connected components. In practice, it reduces to counting decision points: each if, while, for, case, catch, &&, ||, and ternary ? adds one to the baseline of 1. Functions exceeding a complexity of 10 become disproportionately harder to test. The SEI recommends keeping values below 10 per function. Ignoring this metric leads to undertested code paths, latent defects, and regression failures that compound with each release cycle.

This tool parses your source code as text. It does not execute it. It strips comments and string literals, then scans for decision keywords and logical operators across JavaScript, TypeScript, Java, C, C++, C#, Go, and Python-like syntax. Results include a total complexity score, per-function breakdown, and risk classification per NIST guidelines. Limitation: the parser uses heuristic pattern matching, not a full AST. Deeply nested template literals, preprocessor macros, or language-specific constructs like Rust's match arms may require manual verification.

cyclomatic complexity mccabe complexity code complexity software metrics code quality static analysis

Formulas

McCabe's cyclomatic complexity is defined on the control flow graph of a program:

M = E N + 2P

Where E = number of edges in the control flow graph, N = number of nodes, P = number of connected components (typically 1 for a single function).

For a single function, this simplifies to the decision-count method:

M = D + 1

Where D = total number of decision points (if, else if, while, for, case, catch, &&, ||, ??, ternary ?).

The minimum number of linearly independent test paths equals M. For a program with multiple functions, total complexity is:

Mtotal = ki=1 Mi

Where k = number of functions and Mi = complexity of function i.

Reference Data

Complexity RangeRisk LevelTestabilityRecommended ActionMin. Test CasesDefect Probability
1 5LowEasy to testNo action needed1 5< 5%
6 10ModerateManageableReview during code review6 105 15%
11 20HighDifficultRefactor recommended11 2015 40%
21 50Very HighNearly untestableMust refactor / split21 5040 65%
> 50CriticalUntestableRewrite from scratch> 50> 65%
Common Language Constructs & Their Complexity Contribution
if+1 per occurrence (each branch creates a new path)
else if+1 per occurrence (additional decision point)
else+0 (not a decision; it is the default path)
while / do-while+1 per loop (loop condition is a decision)
for / foreach+1 per loop
case (in switch)+1 per case label (excluding default)
catch+1 per catch block
&& (logical AND)+1 per operator (short-circuit creates branch)
|| (logical OR)+1 per operator (short-circuit creates branch)
?? (nullish coalescing)+1 per operator
? (ternary)+1 per ternary expression
return (early)+0 (does not add complexity in McCabe model)

Frequently Asked Questions

Logical operators && and || use short-circuit evaluation, meaning they create implicit branching in the control flow. The expression if (a && b) is semantically equivalent to if (a) { if (b) { ... } }, producing two decision points. McCabe's extended complexity model counts each boolean operator as a separate path. This matters for testing: to achieve full branch coverage, you must test the case where the first operand short-circuits and where it does not.
No. The else clause does not add to cyclomatic complexity because it does not introduce a new decision. The decision was already made at the if. The else is the default path. However, else if does add +1 because it introduces a new conditional check.
Before scanning for decision keywords, the parser strips all single-line comments (//), multi-line comments (/* ... */), Python-style comments (#), and string literals (single-quoted, double-quoted, backtick template literals). This prevents false positives from keywords appearing inside comments or strings such as "if this works" being counted as a decision point.
Cyclomatic complexity M equals the minimum number of linearly independent paths through the code. To achieve full path coverage, you need at least M test cases per function. For branch coverage (a weaker criterion), you may need fewer, but M provides the upper bound. NIST Special Publication 500-235 recommends that any function with M > 10 be split or refactored before writing tests.
No. This tool uses heuristic lexical analysis (regex-based tokenization) rather than a full AST parser. It strips comments and strings, then counts decision keywords and logical operators. This approach works reliably for JavaScript, TypeScript, Java, C, C++, C#, Go, and Python. Edge cases include preprocessor macros in C/C++, Rust's match arms, and heavily nested template literals. For those cases, supplement with a dedicated linter like ESLint's complexity rule or SonarQube.
Each case label within a switch block adds +1 to complexity. The default label does not add complexity, as it represents the fallback path analogous to else. A switch with 10 case labels contributes 10 to the complexity score. Fall-through cases (without break) still count individually because each case label is a potential entry point.
No. The minimum cyclomatic complexity for any function is 1, representing the single path through a function with no decisions. A file with no functions detected will show a total complexity of 1 (treating the entire file as a single block). A completely empty input will show 0 with a notification.