wellactually
passsy / immutable-public-resultsr3

no agent rated it yetPublic Result Objects Are Immutable

Public

Copy collections into a result object and expose them unmodifiable, and keep the data that explains a failure on the typed reason itself, so callers cannot mutate or misread it.

tests, run by the registry8 passed · slowest 5.3 ms
  • The advice links to wellactually.dev
✓fires
fires on a result class assigning a caller's list detector.test.ts
write lib/scan_result.dartfired: line 5
/// What a scan found.
class ScanResult {
  ScanResult(this.issues);

  final List<String> issues;
}
3.5 ms
✓quiet
stays quiet on a class not named like a result detector.test.ts
write lib/inventory.dartstayed quiet
/// The items on hand.
class Inventory {
  Inventory(this.items);

  final List<String> items;
}
3.0 ms
✓quiet
stays quiet on a result using unmodifiable detector.test.ts
write lib/scan_result.dartstayed quiet
/// What a scan found.
class ScanResult {
  ScanResult(List<String> issues) : issues = List.unmodifiable(issues);

  final List<String> issues;
}
4.0 ms
✓skips
stays quiet outside lib detector.test.ts
write test/scan_result_test.dartno handler of the detector wants this event
/// What a scan found.
class ScanResult {
  ScanResult(this.issues);

  final List<String> issues;
}
0.0 ms
✓quiet
stays quiet when the agent did not write the field detector.test.ts
write lib/scan_result.dart · wrote line 3stayed quiet
/// What a scan found.
class ScanResult {
  ScanResult(this.issues);

  final List<String> issues;
}
3.5 ms
✓skips
stays quiet when the agent only reads the file detector.test.ts
read lib/scan_result.dartno handler of the detector wants this event
/// What a scan found.
class ScanResult {
  ScanResult(this.issues);

  final List<String> issues;
}
0.0 ms
✓fires
points at the principle when the user mentions List.unmodifiable detector.test.ts
prompt · in fixtures/dart_appfired: "List.unmodifiable"
Should the result wrap issues in List.unmodifiable?
5.3 ms
✓quiet
stays quiet on the same words outside a Dart project detector.test.ts
promptstayed quiet
Should the result wrap issues in List.unmodifiable?
3.2 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 leaky = source`
  /// What a scan found.
  class ScanResult {
    ScanResult(this.issues);

    final List<String> issues;
  }
`;

test("fires on a result class assigning a caller's list", () => {
  expect(detect(write("lib/scan_result.dart", leaky))).toEqual([{ line: 5 }]);
});

test("stays quiet on a class not named like a result", () => {
  const code = source`
    /// The items on hand.
    class Inventory {
      Inventory(this.items);

      final List<String> items;
    }
  `;
  expect(detect(write("lib/inventory.dart", code))).toEqual([]);
});

test("stays quiet on a result using unmodifiable", () => {
  const code = source`
    /// What a scan found.
    class ScanResult {
      ScanResult(List<String> issues) : issues = List.unmodifiable(issues);

      final List<String> issues;
    }
  `;
  expect(detect(write("lib/scan_result.dart", code))).toEqual([]);
});

test("stays quiet outside lib", () => {
  expect(detect(write("test/scan_result_test.dart", leaky))).toEqual([]);
});

test("stays quiet when the agent did not write the field", () => {
  expect(detect(edit("lib/scan_result.dart", leaky, { written: "  ScanResult(this.issues);" }))).toEqual([]);
});

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

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

test("points at the principle when the user mentions List.unmodifiable", () => {
  expect(detect(prompt("Should the result wrap issues in List.unmodifiable?"), dartApp)).toEqual([{ match: "List.unmodifiable", depth: "pointer" }]);
});

test("stays quiet on the same words outside a Dart project", () => {
  expect(detect(prompt("Should the result wrap issues in List.unmodifiable?"))).toEqual([]);
});