avoid-mutating-parameters

Path
lint/suspicious/avoid-mutating-parameters
Default
Off, opt in
Origin
Falcon
Rule
95 of 512

Detects writes through named function, method and constructor parameter objects. Closure parameters are exempt; parameter rebinding belongs to parameter-assignments. Parameters annotated @mutated (dart-code-metrics-annotations) are exempt.

Invalid

example.dartdart
class Box { int value = 0; Box? child; }
void mutate(Box box, List<int> values, Map<String, int> map) {
  box.value = 1;
  box.value += 1;
  ++box.value;
  box.value--;
  values[0] = 2;
  map['key'] ??= 3;
  box.child!.value = 2;
  box..value = 4;
  values..[0] = 5;
  void nested() { box.value = 6;  }
  final closure = () { values[0]++;  };
  nested(); closure();
}
class Holder {
  set item(Box value) { value.value = 1;  }
}

class Mutator {
  Mutator(Box box) {
    box.value = 1;
  }

  void update(Box box) {
    box.value = 2;
  }

  void operator []=(int index, Box box) {
    box.value = index;
  }
}

void outer() {
  void local(Box box) {
    box.value = 3;
  }
  local(Box());
}

void castReceivers(Object value, Box? box) {
  (value as List<int>)[0] = 1;
  (value as Box).value = 2;
  box!.value = 3;
  (box! as Box).value++;
}
Avoid mutating an object supplied as a parameter.
2void mutate(Box box, List<int> values, Map<String, int> map) {
3 box.value = 1;
Avoid mutating an object supplied as a parameter.
3 box.value = 1;
4 box.value += 1;
Avoid mutating an object supplied as a parameter.
4 box.value += 1;
5 ++box.value;
Avoid mutating an object supplied as a parameter.
5 ++box.value;
6 box.value--;
Avoid mutating an object supplied as a parameter.
6 box.value--;
7 values[0] = 2;
Avoid mutating an object supplied as a parameter.
7 values[0] = 2;
8 map['key'] ??= 3;
Avoid mutating an object supplied as a parameter.
8 map['key'] ??= 3;
9 box.child!.value = 2;
Avoid mutating an object supplied as a parameter.
9 box.child!.value = 2;
10 box..value = 4;
Avoid mutating an object supplied as a parameter.
10 box..value = 4;
11 values..[0] = 5;
Avoid mutating an object supplied as a parameter.
11 values..[0] = 5;
12 void nested() { box.value = 6; }
Avoid mutating an object supplied as a parameter.
12 void nested() { box.value = 6; }
13 final closure = () { values[0]++; };
Avoid mutating an object supplied as a parameter.
16class Holder {
17 set item(Box value) { value.value = 1; }
Avoid mutating an object supplied as a parameter.
21 Mutator(Box box) {
22 box.value = 1;
Avoid mutating an object supplied as a parameter.
25 void update(Box box) {
26 box.value = 2;
Avoid mutating an object supplied as a parameter.
29 void operator []=(int index, Box box) {
30 box.value = index;
Avoid mutating an object supplied as a parameter.
35 void local(Box box) {
36 box.value = 3;
Avoid mutating an object supplied as a parameter.
41void castReceivers(Object value, Box? box) {
42 (value as List<int>)[0] = 1;
Avoid mutating an object supplied as a parameter.
42 (value as List<int>)[0] = 1;
43 (value as Box).value = 2;
Avoid mutating an object supplied as a parameter.
43 (value as Box).value = 2;
44 box!.value = 3;
Avoid mutating an object supplied as a parameter.
44 box!.value = 3;
45 (box! as Box).value++;

Valid

example.dartdart
class Box { int value = 0; }
void noMutation(Box box, List<int> values) {
  final local = Box();
  local.value = 1;
  final copy = [...values];
  copy[0] = 2;
  final read = box.value;
  box = Box(); // Rebinding belongs to parameter-assignments.
  {
    final box = Box();
    box.value = read;
  }
  void nested() { final box = Box(); box.value++; }
  final callback = () { final values = [0]; values[0]++; };
  nested(); callback();
}
class Owner {
  Box box;
  Owner(this.box) { box.value = 1; }
}
const mutated = 0;
void intentional(@mutated Box box, @mutated List<int> values) {
  box.value = 1;
  values[0]++;
}
class AnnotatedSetter {
  set item(@mutated Box value) { value.value++; }
}

class Builder { String name = ''; }
class Options { final headers = <String, String>{}; }
class Item { bool selected = true; }

void closures(List<Item> items) {
  final build = (Builder b) => b..name = 'x';
  final intercept = (Options options) {
    options.headers['Authorization'] = 'token';
  };
  items.forEach((i) => i.selected = false);
  build(Builder());
  intercept(Options());
}

Configure avoid-mutating-parameters

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "avoid-mutating-parameters": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/suspicious/avoid-mutating-parameters: <reason>