prefer-collection-literals

Same as prefer_collection_literals in Dart lints

Group
Style
Path
lint/style/prefer-collection-literals
Default
On (recommended)
Origin
Dart lints
Rule
322 of 512
recommended

Flags no-argument collection constructor calls that a literal would express.

The empty List(), Map(), Set(), LinkedHashMap(), and LinkedHashSet() constructors are more verbose than the equivalent [] or {} literals, which are the idiomatic way to build a fresh collection and read more clearly. The rule matches the unnamed and .new constructors written as a plain call (List(), Set.new()), an explicit new expression (new Map()), or with type arguments (Map<K, V>()). It deliberately spares named constructors such as List.filled or Map.of and any invocation carrying arguments, since those have no literal form.

Two further facts withhold a diagnostic that would otherwise change semantics:

  • Concrete context — a LinkedHashMap() / LinkedHashSet() whose declared context type (a variable/field/top-level/return annotation) is that concrete type. A {} literal has static type Map/Set, which is not assignable back to LinkedHashMap/LinkedHashSet, so the constructor is required. This check is purely syntactic and applies without a type index. Local functions and operators use their own return annotations, never their enclosing function's.
  • Shadowed or unresolved identity — a List()/Map()/Set()/… whose resolved declaration is not the SDK collection, or whose library/import graph cannot establish that identity. A literal could construct a different type. Without an identity index, the rule remains syntactic and such a constructor keeps firing.

Everything else — including any var/unannotated context, and a concrete constructor reached only through a nested argument position — keeps firing.

Invalid

example.dartdart
import 'dart:collection';

void bad() {
  var a = List();
  var b = Map();
  var c = Set();
  var d = LinkedHashMap();
  var e = LinkedHashSet();
  var f = List<int>();
  var g = new Set();
  var h = new Map<String, int>();
}

// A `{}` literal has static type `Map`, which IS assignable to a declared `Map`
// context — the concrete-type exception does not apply, so the diagnostic keeps
// firing. Only `LinkedHashMap`/`LinkedHashSet` contexts suppress.
void nonConcreteContext() {
  Map<int, int> m = LinkedHashMap();
  var n = LinkedHashMap();
}
Use a collection literal instead of a constructor invocation.
3void bad() {
4 var a = List();
Use a collection literal instead of a constructor invocation.
4 var a = List();
5 var b = Map();
Use a collection literal instead of a constructor invocation.
5 var b = Map();
6 var c = Set();
Use a collection literal instead of a constructor invocation.
6 var c = Set();
7 var d = LinkedHashMap();
Use a collection literal instead of a constructor invocation.
7 var d = LinkedHashMap();
8 var e = LinkedHashSet();
Use a collection literal instead of a constructor invocation.
8 var e = LinkedHashSet();
9 var f = List<int>();
Use a collection literal instead of a constructor invocation.
9 var f = List<int>();
10 var g = new Set();
Use a collection literal instead of a constructor invocation.
10 var g = new Set();
11 var h = new Map<String, int>();
Use a collection literal instead of a constructor invocation.
17void nonConcreteContext() {
18 Map<int, int> m = LinkedHashMap();
Use a collection literal instead of a constructor invocation.
18 Map<int, int> m = LinkedHashMap();
19 var n = LinkedHashMap();

Valid

example.dartdart
import 'dart:collection';

void good() {
  var a = [];
  var b = {};
  var c = <int>[];
  var d = <String, int>{};
  var e = List.filled(3, 0);
  var f = Map.from(<int, int>{});
  var g = Set.of([1, 2, 3]);
  var h = List.generate(3, (i) => i);
}

// A `{}`/`{}` literal has static type `Map`/`Set`, which is not assignable back
// to the concrete `LinkedHashMap`/`LinkedHashSet`, so these constructors are
// REQUIRED by their declared context type and the diagnostic is SUPPRESSED. This
// holds for local variables, fields, and return types.
// (This suppression is syntactic and does not need a type index, but the file as
// a whole exercises the user-shadow suppression below, which does.)
LinkedHashMap<int, int> makeMap() => LinkedHashMap();

class Holder {
  LinkedHashSet<int> data = LinkedHashSet();

  LinkedHashMap<int, int> build() {
    LinkedHashMap<int, int> local = LinkedHashMap();
    return local;
  }
}

// A user-declared `Bag` named `Set` shadows core `Set`. Its `type_kind` is
// `Some` (user declarations carry one; core names do not), so `Set()` builds the
// user's type and a `{}` literal would build the wrong one — SUPPRESSED.
// (Requires the corpus harness to attach a TypeIndex for this rule; without one
// the name is Unknown and this line would fire.)
class Set {}

void shadowed() {
  var s = Set();
}

Configure prefer-collection-literals

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-collection-literals": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/prefer-collection-literals: <reason>