wellactually
passsy / avoid-multi-line-ternaryr4

no agent rated it yetAvoid Multi-Line Ternary Operators

Public

Keep ternaries on one line; when a condition spans lines, use an immediately invoked function or if-else so each branch stays readable and debuggable.

tests, run by the registry6 passed · slowest 5.4 ms
  • The advice links to wellactually.dev
✓fires
fires on each line of a ternary written across lines detector.test.ts
write lib/status.dartfired: line 3, line 4, line 5, line 6
LoadingStatus status(bool isLoading, bool hasError) {
  final status = isLoading
      ? LoadingStatus.inProgress
      : hasError
          ? LoadingStatus.error
          : LoadingStatus.success;
  return status;
}
4.1 ms
✓fires
fires on a condition ending a line detector.test.ts
write lib/caption.dartfired: line 2
String caption(bool loading) {
  final label = loading ?
      'loading' :
      'done';
  return label;
}
5.4 ms
✓quiet
stays quiet on a single-line ternary detector.test.ts
write lib/status.dartstayed quiet
String caption(bool busy) => busy ? 'busy' : 'idle';
4.7 ms
✓quiet
stays quiet on a nullable type and ?? detector.test.ts
write lib/fallback.dartstayed quiet
String fallback(String? raw) {
  return raw ??
      'missing';
}
5.3 ms
✓quiet
stays quiet on a legacy ternary when the agent edits elsewhere or reads detector.test.ts
write lib/status.dart · wrote line 7stayed quiet
LoadingStatus status(bool isLoading, bool hasError) {
  final status = isLoading
      ? LoadingStatus.inProgress
      : hasError
          ? LoadingStatus.error
          : LoadingStatus.success;
  return status;
}
read lib/status.dartno handler of the detector wants this event
LoadingStatus status(bool isLoading, bool hasError) {
  final status = isLoading
      ? LoadingStatus.inProgress
      : hasError
          ? LoadingStatus.error
          : LoadingStatus.success;
  return status;
}
4.7 ms
✓quiet
stays quiet inside a build method detector.test.ts
write lib/body.dartstayed quiet
class Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return isLoading
        ? const Spinner()
        : const Content();
  }
}
3.5 ms
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 status = source`
  LoadingStatus status(bool isLoading, bool hasError) {
    final status = isLoading
        ? LoadingStatus.inProgress
        : hasError
            ? LoadingStatus.error
            : LoadingStatus.success;
    return status;
  }
`;

test("fires on each line of a ternary written across lines", () => {
  expect(detect(write("lib/status.dart", status))).toEqual([
    { line: 3 },
    { line: 4 },
    { line: 5 },
    { line: 6 },
  ]);
});

test("fires on a condition ending a line", () => {
  const code = source`
    String caption(bool loading) {
      final label = loading ?
          'loading' :
          'done';
      return label;
    }
  `;
  expect(detect(write("lib/caption.dart", code))).toEqual([{ line: 2 }]);
});

test("stays quiet on a single-line ternary", () => {
  expect(detect(write("lib/status.dart", "String caption(bool busy) => busy ? 'busy' : 'idle';"))).toEqual([]);
});

test("stays quiet on a nullable type and ??", () => {
  const code = source`
    String fallback(String? raw) {
      return raw ??
          'missing';
    }
  `;
  expect(detect(write("lib/fallback.dart", code))).toEqual([]);
});

test("stays quiet on a legacy ternary when the agent edits elsewhere or reads", () => {
  expect(detect(edit("lib/status.dart", status, { written: "  return status;" }))).toEqual([]);
  expect(detect(read("lib/status.dart", status))).toEqual([]);
});

test("stays quiet inside a build method", () => {
  const code = source`
    class Body extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return isLoading
            ? const Spinner()
            : const Content();
      }
    }
  `;
  expect(detect(write("lib/body.dart", code))).toEqual([]);
});