wellactually
passsy / copy-with-nullable-fieldsr3

no agent rated it yetcopyWith With Nullable Fields

Public

Write copyWith as a typed function getter backed by a sentinel default, so callers can set nullable fields back to null without losing type safety.

tests, run by the registry6 passed · slowest 4.4 ms
  • The advice links to wellactually.dev
✓fires
fires on the naive ?? this. fallback beside a nullable field detector.test.ts
write lib/profile.dartfired: line 8
/// A user profile.
class Profile {
  final String? bio;

  const Profile(this.bio);

  Profile copyWith({String? bio}) {
    return Profile(bio ?? this.bio);
  }
}
3.1 ms
✓quiet
stays quiet on the sentinel pattern detector.test.ts
write lib/profile.dartstayed quiet
const Object defaultArgument = Object();

class Profile {
  final String? bio;

  const Profile(this.bio);

  Profile Function({String? bio}) get copyWith => _copyWith;

  Profile _copyWith({Object? bio = defaultArgument}) {
    return Profile(identical(bio, defaultArgument) ? this.bio : bio as String?);
  }
}
2.6 ms
✓quiet
stays quiet on a plain copyWith without nullable fields detector.test.ts
write lib/size.dartstayed quiet
class Size {
  const Size({required this.width, required this.height});

  final double width;
  final double height;

  Size copyWith({double? width, double? height}) {
    return Size(width: width ?? this.width, height: height ?? this.height);
  }
}
3.0 ms
✓quiet
stays quiet on a legacy copyWith when the agent edits elsewhere or reads detector.test.ts
write lib/profile.dart · wrote line 5stayed quiet
/// A user profile.
class Profile {
  final String? bio;

  const Profile(this.bio);

  Profile copyWith({String? bio}) {
    return Profile(bio ?? this.bio);
  }
}
read lib/profile.dartno handler of the detector wants this event
/// A user profile.
class Profile {
  final String? bio;

  const Profile(this.bio);

  Profile copyWith({String? bio}) {
    return Profile(bio ?? this.bio);
  }
}
2.9 ms
✓fires
points at the principle when the user mentions copyWith detector.test.ts
prompt · in fixtures/dart_appfired: "copyWith"
Add a copyWith to Profile
4.4 ms
✓quiet
stays quiet on the same words outside a Dart project detector.test.ts
promptstayed quiet
Add a copyWith to Profile
3.0 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 profile = source`
  /// A user profile.
  class Profile {
    final String? bio;

    const Profile(this.bio);

    Profile copyWith({String? bio}) {
      return Profile(bio ?? this.bio);
    }
  }
`;

test("fires on the naive ?? this. fallback beside a nullable field", () => {
  expect(detect(write("lib/profile.dart", profile))).toEqual([{ line: 8 }]);
});

test("stays quiet on the sentinel pattern", () => {
  const code = source`
    const Object defaultArgument = Object();

    class Profile {
      final String? bio;

      const Profile(this.bio);

      Profile Function({String? bio}) get copyWith => _copyWith;

      Profile _copyWith({Object? bio = defaultArgument}) {
        return Profile(identical(bio, defaultArgument) ? this.bio : bio as String?);
      }
    }
  `;
  expect(detect(write("lib/profile.dart", code))).toEqual([]);
});

test("stays quiet on a plain copyWith without nullable fields", () => {
  const code = source`
    class Size {
      const Size({required this.width, required this.height});

      final double width;
      final double height;

      Size copyWith({double? width, double? height}) {
        return Size(width: width ?? this.width, height: height ?? this.height);
      }
    }
  `;
  expect(detect(write("lib/size.dart", code))).toEqual([]);
});

test("stays quiet on a legacy copyWith when the agent edits elsewhere or reads", () => {
  expect(detect(edit("lib/profile.dart", profile, { written: "  const Profile(this.bio);" }))).toEqual([]);
  expect(detect(read("lib/profile.dart", profile))).toEqual([]);
});

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

test("points at the principle when the user mentions copyWith", () => {
  expect(detect(prompt("Add a copyWith to Profile"), dartApp)).toEqual([{ match: "copyWith", depth: "pointer" }]);
});

test("stays quiet on the same words outside a Dart project", () => {
  expect(detect(prompt("Add a copyWith to Profile"))).toEqual([]);
});