prefer_add_all
v0.8.0 Warning Fix Collection Type
Flags two ways of adding elements one at a time: a for-in loop whose only statement adds the loop variable, and two or more consecutive add calls on the same collection. The quick fix collapses either into addAll.
A copy loop is addAll spelled out across three lines. The reader has to follow the control flow to work out it is a single operation:
List<String> withDefaults(List<String> configured) { final result = <String>[];
for (final tag in configured) { result.add(tag); }
return result;}List<String> withDefaults(List<String> configured) { final result = <String>[];
result.addAll(configured);
return result;}addAll also lets a List grow its backing store once instead of on each add.
Consecutive add calls
Section titled “Consecutive add calls”A run of add calls on the same receiver is one addAll with a literal:
// Don'tfinal steps = <String>[];steps.add('validate');steps.add('persist');steps.add('notify');
// Dofinal steps = <String>[];steps.addAll(['validate', 'persist', 'notify']);The run has to be uninterrupted. Any other statement between the calls breaks it, and neither half is reported:
// Accepted — the log call splits the runsteps.add('validate');log('validating');steps.add('persist');Known limitations
Section titled “Known limitations”For the loop form, only an exact copy is reported. The rule stays silent whenever the loop does anything else:
- The added value is not the loop variable unchanged.
result.add(tag.trim())is a map, not a copy — reach foraddAll(configured.map((t) => t.trim()))yourself. - The body has more than one statement, or wraps the
addin a condition. - The loop is indexed (
for (var i = 0; ...)) rather thanfor-in, since it may skip or reorder elements. - The receiver depends on the loop variable.
groups.putIfAbsent(key(item), () => []).add(item)distributes the source across a different target per iteration, and has noaddAllequivalent. - The method is anything other than
add—insert,addEntriesand the rest are untouched.
For consecutive calls, the receiver must be a plain variable or property chain. items[i].add(x) may denote a different object on each call, so it is left alone — and the receiver must resolve to a collection, since add exists on many unrelated types.
Configuration
Section titled “Configuration”This rule is in the opinionated preset, so it is on with
preset: opinionated, or by name.
To turn it off:
rules: prefer_add_all: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”list_all_equatable_fields— Ensure all fields are listed in Equatable props.avoid_accessing_collections_by_constant_index— Avoid accessing a collection by a constant index inside a loop.avoid_collection_equality_checks— Avoid comparing collections with == or != as it checks reference equality, not contents.avoid_collection_methods_with_unrelated_types— Avoid calling collection methods with arguments whose types are unrelated to the collection’s type parameter.