unnecessary-statements
Same as unnecessary_statements in Dart lints
- Group
- Correctness
- Path
lint/correctness/unnecessary-statements- Default
- On (recommended)
- Origin
- Dart lints
- Rule
- 472 of 512
Flags expression statements whose expression has no clear effect.
A statement such as x;, 1 + 2;, list.clear; or c ? a : b; computes a
value and throws it away, which usually means the author forgot a call, an
assignment, or a return. Expressions with a clear effect are allowed:
assignments, invocations, instance creations, await, throw, rethrow,
cascades, as casts, postfix operators (x++, x!) and prefix ++/--.
The right operand of &&, ||, and ??, and both branches of a
conditional, are checked in turn, since those operators are used for control
flow. A parenthesized expression is always reported, as are binary
operations, index reads, literals, and is tests.
Identifiers and resolved property reads are reported unless they denote an
explicitly declared getter, which may have side effects. Dynamic reads and
unresolved identifiers are reported too. Applicable extension getters are
allowed, while property reads of unavailable external members are
conservatively left alone. The same checks apply to the initializer and
updaters of a for (;;) loop with an expression initializer. A cascade
section that reads a method or function-valued member (..clear) is reported.
Constructor and generic function tear-offs are references without an effect.
Reading a function's synthetic call member is also a tear-off, including
null-aware reads and cascade sections; invoking it still has an effect.
void f(List<int> list, int a, int b) {
a; // flagged
list.clear; // flagged
a + b; // flagged
list.clear(); // ok
}
Invalid
int topLevel = 0;
void topFunction() {}
int methodOne() => 1;
int methodTwo() => 2;
class Box {
int value = 0;
static int count = 0;
void tick() {}
void run(List<int> list, bool foo, int a, int b) {
value;
this.value;
tick;
Box.count;
list..clear;
}
}
void f(List<int> list, bool foo, int a, int b, Box box) {
a;
list.clear;
1 + 2;
methodOne() + methodTwo();
foo ? a : b;
topLevel;
topFunction;
box.value;
box.tick;
'string';
list[0];
a is int;
-a;
[1, 2];
foo && a > 0;
(methodOne());
Box;
for (a; a < 10; a + 1) {}
}
void dynamicReads(dynamic value) {
value.missing;
value.first.last;
unknownName;
unknownPrefix.member;
}
class MissingMember {
void test() {
this.missing;
}
}
class FunctionValues {
void Function() callback = () {};
void Function() get getter => callback;
}
void functionCascades(FunctionValues value) {
value..callback;
value..getter;
}
extension BoxMethods on Box {
void extensionMethod() {}
}
void extensionMethodTearoff(Box box) {
box.extensionMethod;
} void run(List<int> list, bool foo, int a, int b) { value; value; this.value; this.value; tick; tick; Box.count; Box.count; list..clear;void f(List<int> list, bool foo, int a, int b, Box box) { a; a; list.clear; list.clear; 1 + 2; 1 + 2; methodOne() + methodTwo(); methodOne() + methodTwo(); foo ? a : b; methodOne() + methodTwo(); foo ? a : b; foo ? a : b; topLevel; topLevel; topFunction; topFunction; box.value; box.value; box.tick; box.tick; 'string'; 'string'; list[0]; list[0]; a is int; a is int; -a; -a; [1, 2]; [1, 2]; foo && a > 0; foo && a > 0; (methodOne()); (methodOne()); Box; Box; for (a; a < 10; a + 1) {} Box; for (a; a < 10; a + 1) {}void dynamicReads(dynamic value) { value.missing; value.missing; value.first.last; value.first.last; unknownName; unknownName; unknownPrefix.member; void test() { this.missing;void functionCascades(FunctionValues value) { value..callback; value..callback; value..getter;void extensionMethodTearoff(Box box) { box.extensionMethod;Valid
int get topGetter => 0;
int methodOne() => 1;
int methodTwo() => 2;
class Some {
const Some();
int get computed => 1;
void method() {}
void run() {
computed;
this.computed;
}
}
Future<void> f(List<int> list, Some some, bool foo, int? a, int b, Object o) async {
some.method();
const Some();
Some();
methodOne();
methodTwo();
foo ? methodOne() : methodTwo();
foo && list.remove(1);
a ?? methodOne();
a = 3;
b++;
++b;
a!;
o as int;
await Future.value(1);
list..add(1)..clear();
some.computed;
topGetter;
for (var i = 0; i < b; i++) {}
}
int g(int x) {
return x;
}
void h(Object e) {
try {
throw e;
} catch (_) {
rethrow;
}
}
int arrow(int x) => x;
void annotatedLocalFunctions() {
@pragma('vm:prefer-inline')
void local() {}
local();
}
abstract class GetterInterface {
int get value;
}
class ForwardingGetter implements GetterInterface {
@override
dynamic noSuchMethod(Invocation invocation) => 0;
}
void inheritedGetter(ForwardingGetter value) {
value.value;
}
void functionReturnGetter(GetterInterface Function() create) {
final value = create();
value.value;
}
void declaredForUpdates() {
for (var i = 0; i < 1; i + 1) {}
}
extension<T> on Future<T> {
void get unawaited {}
}
void extensionGetter(Future<void> Function() work) {
// An extension getter may have side effects.
work().then((_) {}).unawaited;
}
class Box {}
extension BoxEffects on Box {
void get effect {}
}
void localExtensionGetter(Box box) {
box.effect;
}Configure unnecessary-statements
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"unnecessary-statements": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/unnecessary-statements: <reason>More correctness rules
- unrelated-type-equality-checks
unrelated_type_equality_checksrecommendedReports
==/!=comparisons and relational==/!=patterns whose operand types are unrelated. - unused-code
check-unused-codecross-fileReport public top-level declarations that nothing references.
- unused-dependenciescross-file
Report regular pubspec dependencies with no Dart import or export in the analyzed package.
- unused-files
check-unused-filescross-fileReport
lib/files that no project entrypoint can reach. - use-build-context-synchronously
use_build_context_synchronouslyrecommendedflutterFlags
BuildContextuse after an asynchronous gap without a mounted guard. - use-closest-build-contextrecommendedflutter
Use the nearest
BuildContextparameter inside nested callbacks. - use-key-in-widget-constructors
use_key_in_widget_constructorsrecommendedflutterRequire public widget constructors to accept or initialize a Flutter
Key. - use-once-constructors-once-provider
use_once_constructors_once_providerflutterRequire Riverpod once-providers to be created through
.once().