Nested Switch Statement
ID |
javascript.no_nested_switch |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
JavaScript |
Tags |
code-style, complexity |
Description
Reports a switch written inside another switch. The inner switch is the one reported, since that is the statement to pull out into its own function; nesting several levels deep reports every inner level.
Intervening statements do not break the nesting — a switch reached through an if or a loop inside a case is still nested. A function boundary does break it, so a switch inside a callback, an arrow function or a method declared within a case is left alone.
Rationale
// Bad
switch (kind) {
case "text":
switch (encoding) {
case "utf8": return decodeUtf8(buf);
default: break; // leaves the inner switch only
}
return decodeAscii(buf);
default:
return null;
}
-
The reader has to hold two independent selector values and two sets of case labels in mind at once.
-
An inner
breakreads as if it might leave the outer switch, which is a frequent source of cases wired to the wrong branch. -
Adding a case to either switch multiplies the paths a reviewer has to check, so the combined statement grows harder to change than the two separate ones.
Remediation
Extract the inner switch into its own named function and call it from the case.
// Good
function decodeText(buf, encoding) {
switch (encoding) {
case "utf8": return decodeUtf8(buf);
default: return decodeAscii(buf);
}
}
switch (kind) {
case "text": return decodeText(buf, encoding);
default: return null;
}