avoid-unnecessary-collections

Path
lint/performance/avoid-unnecessary-collections
Default
Off, opt in
Origin
Falcon
Rule
157 of 512

Avoid singleton collection literals where SDK APIs accept a single value.

Only plain singleton lists/sets and semantically resolved SDK receivers are checked. Collection control flow, spreads, maps, dynamic/custom APIs and named arguments are excluded. Future.wait is checked only for a discarded awaited result, because replacing it changes List to T. Future.any is excluded when its result is discarded, to preserve its error listener.

Invalid

example.dartdart
import 'dart:async';
import 'dart:async' as async;

void append(List<int> list, Set<int> set) {
  list.addAll([1]);
  list.addAll({2});
  set.addAll([3]);
  set.addAll({4});
  set.containsAll({5});
}
Future<void> futures(Future<int> value) async {
  await Future.wait([value]);
  await async.Future.any([value]);
}
Stream<int> fromFuture(Future<int> value) => Stream.fromFutures([value]);
Stream<int> fromValue(int value) => async.Stream.fromIterable([value]);
Future<int> first(Future<int> value) {
  return Future.any([value]);
}
Future<int> assigned(Future<int> value) {
  final result = Future.any([value]);
  return result;
}
void awaitedArrow(Future<int> value) async => Future.any([value]);
void consumedSwitch(Future<int> value) => switch (Future.any([value])) {
  final result => result.ignore(),
};
This singleton collection is unnecessary. Use `add` with its single element instead.
4void append(List<int> list, Set<int> set) {
5 list.addAll([1]);
This singleton collection is unnecessary. Use `add` with its single element instead.
5 list.addAll([1]);
6 list.addAll({2});
This singleton collection is unnecessary. Use `add` with its single element instead.
6 list.addAll({2});
7 set.addAll([3]);
This singleton collection is unnecessary. Use `add` with its single element instead.
7 set.addAll([3]);
8 set.addAll({4});
This singleton collection is unnecessary. Use `contains` with its single element instead.
8 set.addAll({4});
9 set.containsAll({5});
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
11Future<void> futures(Future<int> value) async {
12 await Future.wait([value]);
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
12 await Future.wait([value]);
13 await async.Future.any([value]);
This singleton collection is unnecessary. Use `Stream.fromFuture` with its single element instead.
14}
15Stream<int> fromFuture(Future<int> value) => Stream.fromFutures([value]);
This singleton collection is unnecessary. Use `Stream.value` with its single element instead.
15Stream<int> fromFuture(Future<int> value) => Stream.fromFutures([value]);
16Stream<int> fromValue(int value) => async.Stream.fromIterable([value]);
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
17Future<int> first(Future<int> value) {
18 return Future.any([value]);
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
20Future<int> assigned(Future<int> value) {
21 final result = Future.any([value]);
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
23}
24void awaitedArrow(Future<int> value) async => Future.any([value]);
Use the single `Future` directly instead of wrapping it in `Future.wait` or `Future.any`.
24void awaitedArrow(Future<int> value) async => Future.any([value]);
25void consumedSwitch(Future<int> value) => switch (Future.any([value])) {

Valid

example.dartdart
import 'dart:async';
class Custom {
  void addAll(Object value) {}
  bool containsAll(Object value) => true;
}
void append(List<int> list, Set<int> set, Map<int, int> map,
    Iterable<int> source, dynamic unknown, bool condition) {
  list.addAll([]);
  list.addAll([1, 2]);
  list.addAll([...source]);
  list.addAll([if (condition) 1]);
  list.addAll([for (final value in source) value]);
  set.containsAll(source);
  map.addAll({1: 2});
  unknown.addAll([1]);
  Custom().addAll([1]);
  Custom().containsAll({1});
}
Future<List<int>> used(Future<int> value) async {
  return await Future.wait([value]);
}
Future<void> options(Future<int> value) async {
  await Future.wait([value], eagerError: true);
  await Future.wait([value], cleanUp: (value) {});
}
Stream<int> multiple(Future<int> first, Future<int> second) => Stream.fromFutures([first, second]);
void shadow(dynamic Future, dynamic Stream) {
  Future.any([1]);
  Stream.fromIterable([1]);
}
void discarded(Future<int> value) {
  Future.any([value]);
  (Future.any([value]));
  Future.any([value])..ignore();
}
void discardedArrow(Future<int> value) => Future.any([value]);

Configure avoid-unnecessary-collections

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "performance": {
        "avoid-unnecessary-collections": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/performance/avoid-unnecessary-collections: <reason>