Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow loops with a body that allows only one iteration (no-unreachable-loop) #1556

Closed
feross opened this issue Oct 21, 2020 · 1 comment
Closed

Comments

@feross
Copy link
Member

feross commented Oct 21, 2020

https://eslint.org/docs/rules/no-unreachable-loop

A loop that can never reach the second iteration is a possible error in the code.

for (let i = 0; i < arr.length; i++) {
    if (arr[i].name === myName) {
        doSomething(arr[i]);
        // break was supposed to be here
    }
    break;
}

In rare cases where only one iteration (or at most one iteration) is intended behavior, the code should be refactored to use if conditionals instead of while, do-while and for loops. It's considered a best practice to avoid using loop constructs for such cases.

Rule Details

This rule aims to detect and disallow loops that can have at most one iteration, by performing static code path analysis on loop bodies.

In particular, this rule will disallow a loop with a body that exits the loop in all code paths. If all code paths in the loop's body will end with either a break, return or a throw statement, the second iteration of such loop is certainly unreachable, regardless of the loop's condition.

This rule checks while, do-while, for, for-in and for-of loops. You can optionally disable checks for each of these constructs.

Examples of incorrect code for this rule:

/*eslint no-unreachable-loop: "error"*/

while (foo) {
    doSomething(foo);
    foo = foo.parent;
    break;
}

function verifyList(head) {
    let item = head;
    do {
        if (verify(item)) {
            return true;
        } else {
            return false;
        }
    } while (item);
}

function findSomething(arr) {
    for (var i = 0; i < arr.length; i++) {
        if (isSomething(arr[i])) {
            return arr[i];
        } else {
            throw new Error("Doesn't exist.");
        }
    }
}

for (key in obj) {
    if (key.startsWith("_")) {
        break;
    }
    firstKey = key;
    firstValue = obj[key];
    break;
}

for (foo of bar) {
    if (foo.id === id) {
        doSomething(foo);
    }
    break;
}

Examples of correct code for this rule:

/*eslint no-unreachable-loop: "error"*/

while (foo) {
    doSomething(foo);
    foo = foo.parent;
}

function verifyList(head) {
    let item = head;
    do {
        if (verify(item)) {
            item = item.next;
        } else {
            return false;
        }
    } while (item);

    return true;
}

function findSomething(arr) {
    for (var i = 0; i < arr.length; i++) {
        if (isSomething(arr[i])) {
            return arr[i];
        }
    }
    throw new Error("Doesn't exist.");
}

for (key in obj) {
    if (key.startsWith("_")) {
        continue;
    }
    firstKey = key;
    firstValue = obj[key];
    break;
}

for (foo of bar) {
    if (foo.id === id) {
        doSomething(foo);
        break;
    }
}

Please note that this rule is not designed to check loop conditions, and will not warn in cases such as the following examples.

Examples of additional correct code for this rule:

/*eslint no-unreachable-loop: "error"*/

do {
    doSomething();
} while (false)

for (let i = 0; i < 1; i++) {
    doSomething(i);
}

for (const a of [1]) {
    doSomething(a);
}
@feross feross added this to the standard 15 milestone Oct 21, 2020
@feross
Copy link
Member Author

feross commented Oct 21, 2020

Only 1 ecosystem failure:

    while ((entry = queue.shift()) != null) {
      setImmediate(next, null, entry)
      return
    }

IMO, this is confusing code since there is never any actual looping.

So let's enable this rule. Shipping in standard v15.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

No branches or pull requests

1 participant