passsy / avoid-records-in-public-apisr3
Avoid Records in Public APIs
PublicUse a named class instead of a record for public return, parameter and field types, because adding a field to a record breaks every caller that destructures it.
tests, run by the registry6 passed · slowest 2.7 ms
✓fires2.7 ms
fires on a named record return type in lib
write lib/measure.dartfired: line 1
({int width, int height}) measure() {
return (width: 1, height: 2);
}✓fires2.7 ms
fires on a named record parameter type in lib
write lib/deploy.dartfired: line 1
void deploy(({String version, String channel}) config) {}✓quiet2.2 ms
stays quiet on a named parameter list
write lib/measure.dartstayed quiet
int measure({int width = 0, int height = 0}) => width * height;✓quiet2.6 ms
stays quiet on a record literal
write lib/pair.dartstayed quiet
void main2() {
final pair = (left: 1, right: 2);
pair.left;
}✓skips0.0 ms
stays quiet outside lib and in tests
write tool/measure.dartno handler of the detector wants this event
({int width, int height}) measure() {
return (width: 1, height: 2);
}write test/measure_test.dartno handler of the detector wants this event
({int width, int height}) measure() {
return (width: 1, height: 2);
}✓quiet2.6 ms
stays quiet on a legacy record when the agent edits elsewhere or reads
write lib/measure.dart · wrote line 2stayed quiet
({int width, int height}) measure() {
return (width: 1, height: 2);
}read lib/measure.dartno handler of the detector wants this event
({int width, int height}) measure() {
return (width: 1, height: 2);
}detector.test.tseach detect() call runs the real detectorEdit
import { expect, test } from "vitest";
import { detect, edit, read, source, write } from "@wellactually/sdk/v3/test";
const measure = source`
({int width, int height}) measure() {
return (width: 1, height: 2);
}
`;
test("fires on a named record return type in lib", () => {
expect(detect(write("lib/measure.dart", measure))).toEqual([{ line: 1 }]);
});
test("fires on a named record parameter type in lib", () => {
expect(detect(write("lib/deploy.dart", "void deploy(({String version, String channel}) config) {}"))).toEqual([
{ line: 1 },
]);
});
test("stays quiet on a named parameter list", () => {
expect(detect(write("lib/measure.dart", "int measure({int width = 0, int height = 0}) => width * height;"))).toEqual([]);
});
test("stays quiet on a record literal", () => {
const code = source`
void main2() {
final pair = (left: 1, right: 2);
pair.left;
}
`;
expect(detect(write("lib/pair.dart", code))).toEqual([]);
});
test("stays quiet outside lib and in tests", () => {
expect(detect(write("tool/measure.dart", measure))).toEqual([]);
expect(detect(write("test/measure_test.dart", measure))).toEqual([]);
});
test("stays quiet on a legacy record when the agent edits elsewhere or reads", () => {
expect(detect(edit("lib/measure.dart", measure, { written: " return (width: 1, height: 2);" }))).toEqual([]);
expect(detect(read("lib/measure.dart", measure))).toEqual([]);
});