avoid-unnecessary-length-check

Group
Style
Path
lint/style/avoid-unnecessary-length-check
Default
Off, opt in
Origin
Falcon
Rule
166 of 512

Empty collections already skip for-in and forEach bodies.

Only a sole iteration guarded by a positive emptiness test is redundant. Restrict receivers to local, SDK collection-typed identifiers: getters, lazy iterables, unknown types and custom collection APIs are not assumed pure. A forEach callback must be a closure, not an expression evaluated for effects.

Invalid

example.dartdart
void inspect(List<int> values, Set<int> unique, Map<int, int> pairs) {
  if (values.isNotEmpty) {
    for (final value in values) { print(value); }
  }
  if (values.length != 0) {
    values.forEach((value) { print(value); });
  }
  if (unique.length > 0) {
    for (final value in unique) { print(value); }
  }
  if (1 <= values.length) {
    values.forEach((value) { print(value); });
  }
  if (pairs.isNotEmpty) {
    pairs.forEach((key, value) { print(key); print(value); });
  }
  if (values.length >= 1)
    for (final value in values) { print(value); }
}
Remove this emptiness guard: iteration already skips empty collections.
1void inspect(List<int> values, Set<int> unique, Map<int, int> pairs) {
2 if (values.isNotEmpty) {
Remove this emptiness guard: iteration already skips empty collections.
4 }
5 if (values.length != 0) {
Remove this emptiness guard: iteration already skips empty collections.
7 }
8 if (unique.length > 0) {
Remove this emptiness guard: iteration already skips empty collections.
10 }
11 if (1 <= values.length) {
Remove this emptiness guard: iteration already skips empty collections.
13 }
14 if (pairs.isNotEmpty) {
Remove this emptiness guard: iteration already skips empty collections.
16 }
17 if (values.length >= 1)

Valid

example.dartdart
class Custom {
  int get length => 2;
  void forEach(void Function(int) callback) { callback(1); }
}
void Function(int) makeCallback() { print('effect'); return print; }
List<int> get changing => <int>[];
void inspect(List<int> values, List<int> other, Iterable<int> lazy, Custom custom, dynamic unknown) {
  if (values.length > 0) print(values[0]);
  if (values.length > 1) { for (final value in values) { print(value); } }
  if (values.isNotEmpty) { for (final value in other) { print(value); } }
  if (values.isNotEmpty) { values.forEach((value) { print(value); }); print('extra'); }
  if (values.isNotEmpty) { values.forEach((value) { print(value); }); } else { print('empty'); }
  if (values.isNotEmpty) { values.forEach(makeCallback()); }
  if (lazy.length > 0) { for (final value in lazy) { print(value); } }
  if (custom.length > 0) { custom.forEach((value) { print(value); }); }
  if (unknown.length > 0) { unknown.forEach((value) { print(value); }); }
  if (changing.isNotEmpty) { for (final value in changing) { print(value); } }
}

class Holder {
  List<int> values = [];
  void inspect() {
    if (values.isNotEmpty) { values.forEach((value) { print(value); }); }
  }
}
class EffectfulHolder extends Holder {
  @override
  List<int> get values { print('read'); return []; }
  @override
  set values(List<int> value) {}
}

Configure avoid-unnecessary-length-check

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "avoid-unnecessary-length-check": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/avoid-unnecessary-length-check: <reason>