prefer-last

Same as prefer-last in Dart Code Metrics

Group
Style
Path
lint/style/prefer-last
Default
Off, opt in
Origin
Dart Code Metrics
Rule
383 of 512

Flags manual last-element indexing in favor of the .last getter.

Catches the xs[xs.length - 1] idiom, where the receiver and the collection whose length is read are the same identifier. Iterables expose a dedicated .last getter that reads more clearly, avoids repeating the receiver, and removes the off-by-one arithmetic that manual indexing invites. The match is deliberately narrow: it requires a literal - 1 subtracted from <name>.length indexing <name>, so unrelated index expressions are left alone.

Invalid

example.dartdart
// Bad: using [list.length - 1] instead of .last
void example() {
  final items = [1, 2, 3];
  final last = items[items.length - 1];
  print(last);
}

class Processor {
  String getLastName(List<String> names) {
    return names[names.length - 1];
  }

  void processTail(List<int> values) {
    final tail = values[values.length - 1];
    if (tail > 0) {
      compute(tail);
    }
  }
}

void multipleViolations(List<String> items) {
  final a = items[items.length - 1];
  final b = items[items.length - 1].length;
  print('$a $b');
}

// Regression: the violation must be found inside Dart 3 containers too.
void containers(List<int> xs, int count) {
  final (a, _) = (xs[xs.length - 1], 0);
  int b;
  int _u;
  (b, _u) = (xs[xs.length - 1], 0);
  lbl: {
    final c = xs[xs.length - 1];
    print(c);
  }
  final d = switch (count) {
    0 => xs[xs.length - 1],
    _ => 0,
  };
  final e = switch (xs[xs.length - 1]) {
    _ => 0,
  };
  final f = [if (count > 0) xs[xs.length - 1]];
  final g = [...[xs[xs.length - 1]]];
  final h = (p: xs[xs.length - 1], q: 0);
  assert(xs[xs.length - 1] > 0, "x");
  print([a, b, d, e, f, g, h]);
}
Prefer `.last` over `[length - 1]` to access the last element.
3 final items = [1, 2, 3];
4 final last = items[items.length - 1];
Prefer `.last` over `[length - 1]` to access the last element.
9 String getLastName(List<String> names) {
10 return names[names.length - 1];
Prefer `.last` over `[length - 1]` to access the last element.
13 void processTail(List<int> values) {
14 final tail = values[values.length - 1];
Prefer `.last` over `[length - 1]` to access the last element.
21void multipleViolations(List<String> items) {
22 final a = items[items.length - 1];
Prefer `.last` over `[length - 1]` to access the last element.
22 final a = items[items.length - 1];
23 final b = items[items.length - 1].length;
Prefer `.last` over `[length - 1]` to access the last element.
28void containers(List<int> xs, int count) {
29 final (a, _) = (xs[xs.length - 1], 0);
Prefer `.last` over `[length - 1]` to access the last element.
31 int _u;
32 (b, _u) = (xs[xs.length - 1], 0);
Prefer `.last` over `[length - 1]` to access the last element.
33 lbl: {
34 final c = xs[xs.length - 1];
Prefer `.last` over `[length - 1]` to access the last element.
37 final d = switch (count) {
38 0 => xs[xs.length - 1],
Prefer `.last` over `[length - 1]` to access the last element.
40 };
41 final e = switch (xs[xs.length - 1]) {
Prefer `.last` over `[length - 1]` to access the last element.
43 };
44 final f = [if (count > 0) xs[xs.length - 1]];
Prefer `.last` over `[length - 1]` to access the last element.
44 final f = [if (count > 0) xs[xs.length - 1]];
45 final g = [...[xs[xs.length - 1]]];
Prefer `.last` over `[length - 1]` to access the last element.
45 final g = [...[xs[xs.length - 1]]];
46 final h = (p: xs[xs.length - 1], q: 0);
Prefer `.last` over `[length - 1]` to access the last element.
46 final h = (p: xs[xs.length - 1], q: 0);
47 assert(xs[xs.length - 1] > 0, "x");

Valid

example.dartdart
// Good: using .last
void example() {
  final items = [1, 2, 3];
  final last = items.last;
  print(last);
}

class Processor {
  String getLastName(List<String> names) {
    return names.last;
  }

  void processTail(List<int> values) {
    final tail = values.last;
    if (tail > 0) {
      compute(tail);
    }
  }
}

void multipleAccess(List<String> items) {
  final a = items.last;
  final b = items.last.length;
  print('$a $b');
}

// OK: accessing non-last indices
void accessOther(List<int> items) {
  final secondToLast = items[items.length - 2];
  final third = items[2];
}

// OK: in loop context
void loopAccess(List<List<int>> matrix) {
  for (int i = 0; i < matrix.length; i++) {
    final row = matrix[i]; // accessing by variable index is OK
  }
}

Configure prefer-last

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

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

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

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