prefer-foreach

Same as prefer_foreach in Dart lints

Path
lint/performance/prefer-foreach
Default
Off, opt in
Origin
Dart lints
Rule
362 of 512

Prefers forEach to a for-in loop that only passes each element to a function.

for (final e in items) f(e); applies f to every element and does nothing else, which items.forEach(f) states directly. The rule fires on a for-in loop that declares its loop variable and whose body (optionally a block with a single statement) is one function or method call taking exactly that variable as its only positional argument. A method call whose receiver mentions the loop variable (e.add(e)) is not a candidate, and neither is a constructor invocation or a call whose argument is implicitly torn off as e.call (a callable object passed where a function is expected).

falcon must prove the callee is a function or method rather than a constructor, so calls through unresolved names are skipped; the analyzer also reports calls to undefined functions.

Invalid

example.dartdart
void log(Object? value) {}

class Sink {
  void add(int value) {}
  static void record(int value) {}
}

class Base {
  final Sink sink = Sink();
}

class Processor extends Base {
  void handle(int value) {}

  // An inherited field as the receiver.
  void inherited(List<int> values) {
    for (final v in values) {
      sink.add(v);
    }
  }

  void run(List<int> values) {
    for (final v in values) {
      handle(v);
    }
  }
}

void examples(List<int> values, Sink sink, void Function(int) callback) {
  for (final v in values) print(v);
  for (var v in values) {
    log(v);
  }
  for (final v in values) sink.add(v);
  for (int v in values) callback(v);
  for (final v in values) Sink.record(v);
  for (final v in values) sink?.add(v);
}
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
16 void inherited(List<int> values) {
17 for (final v in values) {
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
22 void run(List<int> values) {
23 for (final v in values) {
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
29void examples(List<int> values, Sink sink, void Function(int) callback) {
30 for (final v in values) print(v);
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
30 for (final v in values) print(v);
31 for (var v in values) {
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
33 }
34 for (final v in values) sink.add(v);
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
34 for (final v in values) sink.add(v);
35 for (int v in values) callback(v);
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
35 for (int v in values) callback(v);
36 for (final v in values) Sink.record(v);
Use `forEach` and a tear-off rather than a `for` loop to apply a function to every element.
36 for (final v in values) Sink.record(v);
37 for (final v in values) sink?.add(v);

Valid

example.dartdart
class Box {
  Box(this.value);
  Box.named(this.value);
  final int value;
}

class Node {
  void add(Node other) {}
}

class Callable {
  void call() {}
}

void accept(Function callback) {}

void log(Object? value) {}

void examples(List<int> values, List<Node> nodes, int other, List<Callable> callables) {
  values.forEach(print);
  for (final v in values) {
    print(v);
    print(v);
  }
  for (final v in values) print(other);
  for (final v in values) log(v + 1);
  for (final v in values) Box(v);
  for (final v in values) Box.named(v);
  for (final n in nodes) n.add(n);
  int x = 0;
  for (x in values) print(x);
  for (final (a, b) in [(1, 2)]) print(a);
  for (var i = 0; i < 3; i++) print(i);
  // The argument is torn off implicitly as `c.call`.
  for (final c in callables) {
    accept(c);
  }
}

Configure prefer-foreach

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "performance": {
        "prefer-foreach": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/performance/prefer-foreach: <reason>
  • prefer-return-await

    Await returned SDK Futures inside a try body protected by a catch clause.

  • prefer-single-setstateflutter

    Merge consecutive Flutter State.setState statements in the same block.

  • prefer-use-callbackflutter_hooks

    Prefer useCallback for synchronous memoized function literals.

  • prefer-use-memoflutter_hooks

    Prefer memoizing freshly allocated collection values used as hook keys.

  • prefer-using-list-viewflutter

    Suggests considering ListView for a SingleChildScrollView containing a plain Flutter Column with at least two unconditional children in a list literal.

  • sized-box-for-whitespacesized_box_for_whitespacerecommendedflutter

    Flags a Container used only to add fixed width/height whitespace.

  • unnecessary-to-list-in-spreadsunnecessary_to_list_in_spreadsrecommended

    Flags a .toList() call on the operand of a spread, e.g.

  • use-is-even-rather-than-modulouse_is_even_rather_than_modulo

    Prefers isEven/isOdd to comparing x % 2 with 0 or 1.