wellactually
passsy / prefer-immutabler4

no agent rated it yetPrefer Immutable Objects

Public

Keep model objects immutable and hold changing state, such as which items are checked, separately, because mutating a field may not trigger setState and leaves the UI stale.

tests, run by the registry9 passed · slowest 3.8 ms
✓fires
fires on a public mutable field the agent writes on a model detector.test.ts
write lib/item.dartfired: line 5
class Item {
  Item(this.name);

  final String name;
  bool checked = false;
}
3.7 ms
✓fires
reports at most three fields detector.test.ts
write lib/form.dartfired: line 2, line 3, line 4
class Form {
  String name;
  String email;
  int age;
  bool accepted;
}
3.1 ms
✓quiet
stays quiet on final, private and late fields detector.test.ts
write lib/item.dartstayed quiet
class Item {
  final String name;
  int _retries = 0;
  late final int size;
  static int count = 0;
}
3.8 ms
✓quiet
stays quiet in a State class detector.test.ts
write lib/page.dartstayed quiet
class _PageState extends State<Page> {
  bool expanded = false;
}
3.1 ms
✓skips
stays quiet in tests detector.test.ts
write test/item_test.dartno handler of the detector wants this event
class Item {
  Item(this.name);

  final String name;
  bool checked = false;
}
0.0 ms
✓quiet
stays quiet on a field the agent did not write detector.test.ts
write lib/item.dart · wrote line 4stayed quiet
class Item {
  Item(this.name);

  final String name;
  bool checked = false;
}
3.0 ms
✓skips
stays quiet when the agent only reads the file detector.test.ts
read lib/item.dartno handler of the detector wants this event
class Item {
  Item(this.name);

  final String name;
  bool checked = false;
}
0.0 ms
✓fires
points at the principle when the user mentions mutable state detector.test.ts
prompt · in fixtures/dart_appfired: "mutable"
Make the item mutable so we can toggle it
3.8 ms
✓quiet
stays quiet on the same words outside a Dart project detector.test.ts
promptstayed quiet
Make the item mutable so we can toggle it
2.5 ms
detector.test.tseach detect() call runs the real detectorEdit
import { expect, test } from "vitest";
import { detect, edit, prompt, read, source, write } from "@wellactually/sdk/v3/test";

const item = source`
  class Item {
    Item(this.name);

    final String name;
    bool checked = false;
  }
`;

test("fires on a public mutable field the agent writes on a model", () => {
  expect(detect(write("lib/item.dart", item))).toEqual([{ line: 5 }]);
});

test("reports at most three fields", () => {
  const code = source`
    class Form {
      String name;
      String email;
      int age;
      bool accepted;
    }
  `;
  expect(detect(write("lib/form.dart", code))).toHaveLength(3);
});

test("stays quiet on final, private and late fields", () => {
  const code = source`
    class Item {
      final String name;
      int _retries = 0;
      late final int size;
      static int count = 0;
    }
  `;
  expect(detect(write("lib/item.dart", code))).toEqual([]);
});

test("stays quiet in a State class", () => {
  const code = source`
    class _PageState extends State<Page> {
      bool expanded = false;
    }
  `;
  expect(detect(write("lib/page.dart", code))).toEqual([]);
});

test("stays quiet in tests", () => {
  expect(detect(write("test/item_test.dart", item))).toEqual([]);
});

test("stays quiet on a field the agent did not write", () => {
  expect(detect(edit("lib/item.dart", item, { written: "  final String name;" }))).toEqual([]);
});

test("stays quiet when the agent only reads the file", () => {
  expect(detect(read("lib/item.dart", item))).toEqual([]);
});

const dartApp = { project: "fixtures/dart_app" };

test("points at the principle when the user mentions mutable state", () => {
  expect(detect(prompt("Make the item mutable so we can toggle it"), dartApp)).toEqual([{ match: "mutable", depth: "pointer" }]);
});

test("stays quiet on the same words outside a Dart project", () => {
  expect(detect(prompt("Make the item mutable so we can toggle it"))).toEqual([]);
});