π Disallow break and optionally continue in nested loops and switches inside loops.
πΌπ« This rule is enabled in the β
recommended config. This rule is disabled in the βοΈ unopinionated config.
Nested loops can be readable, but break in nested control flow inside loops is easy to misread because the target is not always obvious. Move the inner loop or switch into a function instead.
Set checkContinue to also check continue. This is disabled by default to allow early guards such as those generated by prefer-continue.
Labeled break and continue statements are allowed because their target is explicit.
// β
for (const item of items) {
for (const child of item.children) {
if (child.done) {
break;
}
}
}
// β
function processChildren(item) {
for (const child of item.children) {
if (child.done) {
break;
}
}
}
for (const item of items) {
processChildren(item);
}// β
for (const item of items) {
switch (item.type) {
case 'hidden':
break;
case 'visible':
process(item);
break;
}
}// β
for (const item of items) {
for (const child of item.children) {
check(child);
}
}Type: boolean
Default: false
Also check unlabeled continue statements in nested loops and switches inside loops.
import unicorn from 'eslint-plugin-unicorn';
export default [
unicorn.configs.recommended,
{
rules: {
'unicorn/no-break-in-nested-loop': ['error', {
checkContinue: true,
}],
},
},
];Allowed by default; reported with checkContinue: true:
for (const group of groups) {
for (const item of group) {
if (!item.isValid) {
continue;
}
validate(item);
save(item);
}
}With this option enabled, use a label for continue inside a switch to clarify that it continues the surrounding loop, not the next case.
// β With checkContinue: true
for (const item of items) {
switch (item.type) {
case 'hidden':
continue;
}
process(item);
}
// β
With checkContinue: true
itemsLoop: for (const item of items) {
switch (item.type) {
case 'hidden':
continue itemsLoop;
}
process(item);
}