wellactually
passsy / avoid-sealed-classes-in-public-apisr3

no agent rated it yetAvoid Sealed Classes in Public APIs

Public

Avoid sealed classes and enums in a package's public API when cases may grow, because each new case breaks every caller's exhaustive switch.

tests, run by the registry7 passed · slowest 4.1 ms
✓fires
fires on a public sealed class the agent writes in lib detector.test.ts
write lib/outcome.dartfired: line 1
sealed class Outcome {}

class Ok extends Outcome {}
2.7 ms
✓quiet
stays quiet on a private sealed class detector.test.ts
write lib/outcome.dartstayed quiet
sealed class _Outcome {}
2.5 ms
✓skips
stays quiet outside lib and in tests detector.test.ts
write bin/outcome.dartno handler of the detector wants this event
sealed class Outcome {}

class Ok extends Outcome {}
write test/outcome_test.dartno handler of the detector wants this event
sealed class Outcome {}

class Ok extends Outcome {}
0.0 ms
✓quiet
stays quiet on a legacy sealed class when the agent edits elsewhere or reads detector.test.ts
write lib/outcome.dart · wrote line 3stayed quiet
sealed class Outcome {}

class Ok extends Outcome {}
read lib/outcome.dartno handler of the detector wants this event
sealed class Outcome {}

class Ok extends Outcome {}
2.7 ms
✓quiet
stays quiet on sealed in a comment detector.test.ts
write lib/outcome.dartstayed quiet
// Not a sealed class Outcome on purpose.
class Outcome {}
2.9 ms
✓fires
points at the principle when the user asks about exhaustiveness detector.test.ts
prompt · in fixtures/dart_appfired: "exhaustive"
should this switch be exhaustive
4.1 ms
✓quiet
stays quiet on the same words outside a Dart project detector.test.ts
promptstayed quiet
should this switch be exhaustive
2.6 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 outcome = source`
  sealed class Outcome {}

  class Ok extends Outcome {}
`;

test("fires on a public sealed class the agent writes in lib", () => {
  expect(detect(write("lib/outcome.dart", outcome))).toEqual([{ line: 1 }]);
});

test("stays quiet on a private sealed class", () => {
  expect(detect(write("lib/outcome.dart", "sealed class _Outcome {}"))).toEqual([]);
});

test("stays quiet outside lib and in tests", () => {
  expect(detect(write("bin/outcome.dart", outcome))).toEqual([]);
  expect(detect(write("test/outcome_test.dart", outcome))).toEqual([]);
});

test("stays quiet on a legacy sealed class when the agent edits elsewhere or reads", () => {
  expect(detect(edit("lib/outcome.dart", outcome, { written: "class Ok extends Outcome {}" }))).toEqual([]);
  expect(detect(read("lib/outcome.dart", outcome))).toEqual([]);
});

test("stays quiet on sealed in a comment", () => {
  expect(detect(write("lib/outcome.dart", "// Not a sealed class Outcome on purpose.\nclass Outcome {}"))).toEqual([]);
});

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

test("points at the principle when the user asks about exhaustiveness", () => {
  expect(detect(prompt("should this switch be exhaustive"), dartApp)).toEqual([{ match: "exhaustive", depth: "pointer" }]);
});

test("stays quiet on the same words outside a Dart project", () => {
  expect(detect(prompt("should this switch be exhaustive"))).toEqual([]);
});