Rules / Suspicious / control-flow-in-finally
control-flow-in-finally
Flags return, break, or continue that escapes a finally block.
Control flow leaving a finally overrides whatever the try or catch was doing,
including silently discarding an exception that was still propagating — the
error simply vanishes — and masking any value the try was about to return.
Keep finally blocks limited to cleanup and let exceptions and returns flow
through. A break or continue targeting a loop or switch declared inside
the finally is fine and left alone, as are closures defined within it; only
flow that escapes the finally itself is reported.
Invalid
example.dartdart
int f1() {
try {
doThing();
} finally {
return 1;
}
}
void f2() {
try {
doThing();
} finally {
return;
}
}
void f3(bool cond) {
try {
doThing();
} finally {
if (cond) {
return;
}
}
}
void f4() {
for (var i = 0; i < 10; i++) {
try {
doThing();
} finally {
break;
}
}
}
void f5() {
for (var i = 0; i < 10; i++) {
try {
doThing();
} finally {
continue;
}
}
}
void f6(bool cond) {
for (var i = 0; i < 10; i++) {
try {
doThing();
} finally {
if (cond) break;
}
}
}
Avoid control flow (return/break/continue) that escapes a finally block
4 } finally {
5 return 1;
∙
Avoid control flow (return/break/continue) that escapes a finally block
12 } finally {
13 return;
∙
Avoid control flow (return/break/continue) that escapes a finally block
21 if (cond) {
22 return;
∙
Avoid control flow (return/break/continue) that escapes a finally block
31 } finally {
32 break;
∙
Avoid control flow (return/break/continue) that escapes a finally block
41 } finally {
42 continue;
∙
Avoid control flow (return/break/continue) that escapes a finally block
51 } finally {
52 if (cond) break;
∙
Valid
example.dartdart
void g1() {
try {
doThing();
} finally {
for (var i = 0; i < 10; i++) {
if (i > 5) break;
}
}
}
void g2(int x) {
try {
doThing();
} finally {
switch (x) {
case 1:
break;
default:
break;
}
}
}
void g3() {
try {
doThing();
} finally {
final f = () {
return;
};
f();
}
}
void g4() {
try {
doThing();
} finally {
doCleanup();
}
}
int g5() {
try {
return 1;
} finally {
doCleanup();
}
}
void g6(bool cond) {
try {
doThing();
} finally {
while (cond) {
continue;
}
}
}
How to configure
Set the severity of control-flow-in-finally in your falcon.json:
falcon.jsonjson
{
"linter": {
"rules": {
"suspicious": {
"control-flow-in-finally": "error"
}
}
}
}