Skip to content

avoid_unnecessary_continue

v1.0.0 Warning Fix Control Flow

Flags a continue written as the last statement of a loop body. Control reaches the next iteration whether it is there or not, but the keyword still announces that something below is being skipped — and a reader stops to look for what.

The usual origin: the statements this continue was skipping were moved or deleted, and the guard stayed behind.

class Order {
bool isCancelled = false;
}
void run(List<Order> orders) {
for (final order in orders) {
process(order);
continue;
}
}
void process(Order order) {}
class Order {
bool isCancelled = false;
}
void run(List<Order> orders) {
for (final order in orders) {
process(order);
}
}
void process(Order order) {}

The quick fix deletes the statement, leaving the rest of the body untouched.

A continue that skips something is left alone

Section titled “A continue that skips something is left alone”

Only the last statement is examined, so the guard-clause form — the reason continue exists — is never reported:

class Order {
bool isCancelled = false;
}
void run(List<Order> orders) {
for (final order in orders) {
if (order.isCancelled) continue;
process(order);
}
}
void process(Order order) {}

A continue at the end of a then branch skips the else and everything after the if, so it is not the last statement of the loop body and is not reported:

class Order {
bool isCancelled = false;
}
void run(List<Order> orders) {
for (final order in orders) {
if (order.isCancelled) {
archive(order);
continue;
}
process(order);
}
}
void process(Order order) {}
void archive(Order order) {}

The rule registers all three loop forms, so a trailing continue reports the same way in each:

void drain(int count) {
var remaining = count;
while (remaining > 0) {
remaining--;
continue; // LINT
}
}

A labelled continue is never reported. continue outer; targets an enclosing loop, so it does change where control goes even when written last.

A loop with no braces is still checked: for (final o in orders) continue; is a body consisting of exactly one continue, and reports.

A continue inside a switch case within the loop body is not the loop body’s last statement, so it is left alone.

This rule is in the opinionated preset, so it is on with preset: opinionated or preset: pedantic, or by name:

many_lints.yaml
rules:
avoid_unnecessary_continue: true

To disable this rule:

many_lints.yaml
rules:
avoid_unnecessary_continue: false

To keep the rule on but skip certain paths, use per-rule exclude.