wellactually
passsy / narrow-try-for-generic-exceptionsr3

no agent rated it yetWrap Only the Call That Throws a Generic Exception

Public

Wrap only the one call you expect to throw FormatException, StateError, TimeoutException and similar generic types, because a wide try cannot tell which statement threw.

tests, run by the registry11 passed · slowest 6.0 ms
✓fires
fires on FormatException around a request, a decode and a parse detector.test.ts
write lib/firmware_reader.dartfired: line 6
Future<Firmware> readFirmware(Device device) async {
  try {
    final response = await connection.request(device, 'fw-version');
    final text = utf8.decode(response);
    return KnownFirmware(Version.parse(text.trim()));
  } on FormatException {
    return const UnknownFirmware();
  } catch (e, stackTrace) {
    await connection.restartSession(device);
    rethrow;
  }
}
5.6 ms
✓quiet
stays quiet when the request is split from the parse detector.test.ts
write lib/firmware_reader.dartstayed quiet
Future<Firmware> readFirmware(Device device) async {
  final List<int> response;
  try {
    response = await connection.request(device, 'fw-version');
  } catch (e, stackTrace) {
    log('reading the firmware version failed', error: e, stackTrace: stackTrace);
    await connection.restartSession(device);
    return const UnknownFirmware();
  }

  final text = utf8.decode(response, allowMalformed: true).trim();
  try {
    return KnownFirmware(Version.parse(text));
  } on FormatException {
    return const UnknownFirmware();
  }
}
6.0 ms
✓fires
fires on both typed clauses around two synchronous parses detector.test.ts
write lib/time_of_day_parser.dartfired: line 6, line 8
TimeOfDay? parseTimeOfDay(String raw) {
  try {
    final hour = int.parse(raw.substring(0, 2));
    final minute = int.parse(raw.substring(3, 5));
    return TimeOfDay(hour: hour, minute: minute);
  } on FormatException catch (e, stackTrace) {
    return null;
  } on RangeError catch (e, stackTrace) {
    return null;
  }
}
3.0 ms
✓quiet
stays quiet on one parse next to statements without calls detector.test.ts
write lib/port_parser.dartstayed quiet
int? parsePort(String raw) {
  try {
    final port = int.parse(raw);
    return port;
  } on FormatException catch (e, stackTrace) {
    return null;
  }
}
3.8 ms
✓fires
fires on TimeoutException around several awaits detector.test.ts
write lib/device_sync.dartfired: line 5
Future<void> sync(Device device) async {
  try {
    await connection.connect(device);
    await connection.upload(device, settings);
  } on TimeoutException catch (e, stackTrace) {
    log('device did not answer', error: e, stackTrace: stackTrace);
    rethrow;
  }
}
4.5 ms
✓quiet
stays quiet on TimeoutException around the one await detector.test.ts
write lib/device_ping.dartstayed quiet
Future<bool> isReachable(Device device) async {
  try {
    final pong = await connection.ping(device);
    return pong.isValid;
  } on TimeoutException catch (e, stackTrace) {
    return false;
  }
}
3.9 ms
✓quiet
stays quiet on a broad on Exception around a large block detector.test.ts
write lib/firmware_reader.dartstayed quiet
Future<Firmware> readFirmware(Device device) async {
  try {
    final response = await connection.request(device, 'fw-version');
    final text = utf8.decode(response);
    return KnownFirmware(Version.parse(text.trim()));
  } on Exception catch (e, stackTrace) {
    log('reading the firmware version failed', error: e, stackTrace: stackTrace);
    rethrow;
  }
}
4.0 ms
✓skips
stays quiet in a test asserting the throw detector.test.ts
write test/process_lister_test.dartno handler of the detector wants this event
void main() {
  test('throws without a shell', () async {
    try {
      final result = await lister.processes();
      fail('should have thrown, got $result');
    } on StateError catch (e, stackTrace) {
      // expected
    }
  });
}
0.0 ms
✓quiet
stays quiet on a wide try that is commented out detector.test.ts
write lib/firmware_reader.dartstayed quiet
// try {
//   final response = await connection.request(device, 'fw-version');
//   return KnownFirmware(Version.parse(utf8.decode(response)));
// } on FormatException {
//   return const UnknownFirmware();
// }
void unused() {}
4.4 ms
✓quiet
stays quiet when an edit only touches the handler of a wide try detector.test.ts
write lib/config_loader.dart · wrote line 6stayed quiet
Future<Config> loadConfig(File file) async {
  try {
    final raw = await file.readAsString();
    return Config.fromJson(jsonDecode(raw));
  } on FormatException catch (e, stackTrace) {
    throw ConfigException(file.path);
  }
}
3.7 ms
✓skips
stays quiet when the agent only reads the file detector.test.ts
read lib/config_loader.dartno handler of the detector wants this event
Future<Config> loadConfig(File file) async {
  try {
    final raw = await file.readAsString();
    return Config.fromJson(jsonDecode(raw));
  } on FormatException catch (e, stackTrace) {
    throw ConfigException(file.path);
  }
}
0.0 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";

test("fires on FormatException around a request, a decode and a parse", () => {
  const code = source`
    Future<Firmware> readFirmware(Device device) async {
      try {
        final response = await connection.request(device, 'fw-version');
        final text = utf8.decode(response);
        return KnownFirmware(Version.parse(text.trim()));
      } on FormatException {
        return const UnknownFirmware();
      } catch (e, stackTrace) {
        await connection.restartSession(device);
        rethrow;
      }
    }
  `;
  expect(detect(write("lib/firmware_reader.dart", code))).toEqual([{ line: 6 }]);
});

test("stays quiet when the request is split from the parse", () => {
  const code = source`
    Future<Firmware> readFirmware(Device device) async {
      final List<int> response;
      try {
        response = await connection.request(device, 'fw-version');
      } catch (e, stackTrace) {
        log('reading the firmware version failed', error: e, stackTrace: stackTrace);
        await connection.restartSession(device);
        return const UnknownFirmware();
      }

      final text = utf8.decode(response, allowMalformed: true).trim();
      try {
        return KnownFirmware(Version.parse(text));
      } on FormatException {
        return const UnknownFirmware();
      }
    }
  `;
  expect(detect(write("lib/firmware_reader.dart", code))).toEqual([]);
});

test("fires on both typed clauses around two synchronous parses", () => {
  const code = source`
    TimeOfDay? parseTimeOfDay(String raw) {
      try {
        final hour = int.parse(raw.substring(0, 2));
        final minute = int.parse(raw.substring(3, 5));
        return TimeOfDay(hour: hour, minute: minute);
      } on FormatException catch (e, stackTrace) {
        return null;
      } on RangeError catch (e, stackTrace) {
        return null;
      }
    }
  `;
  expect(detect(write("lib/time_of_day_parser.dart", code))).toEqual([
    { line: 6 },
    { line: 8 },
  ]);
});

test("stays quiet on one parse next to statements without calls", () => {
  const code = source`
    int? parsePort(String raw) {
      try {
        final port = int.parse(raw);
        return port;
      } on FormatException catch (e, stackTrace) {
        return null;
      }
    }
  `;
  expect(detect(write("lib/port_parser.dart", code))).toEqual([]);
});

test("fires on TimeoutException around several awaits", () => {
  const code = source`
    Future<void> sync(Device device) async {
      try {
        await connection.connect(device);
        await connection.upload(device, settings);
      } on TimeoutException catch (e, stackTrace) {
        log('device did not answer', error: e, stackTrace: stackTrace);
        rethrow;
      }
    }
  `;
  expect(detect(write("lib/device_sync.dart", code))).toEqual([{ line: 5 }]);
});

test("stays quiet on TimeoutException around the one await", () => {
  const code = source`
    Future<bool> isReachable(Device device) async {
      try {
        final pong = await connection.ping(device);
        return pong.isValid;
      } on TimeoutException catch (e, stackTrace) {
        return false;
      }
    }
  `;
  expect(detect(write("lib/device_ping.dart", code))).toEqual([]);
});

test("stays quiet on a broad on Exception around a large block", () => {
  const code = source`
    Future<Firmware> readFirmware(Device device) async {
      try {
        final response = await connection.request(device, 'fw-version');
        final text = utf8.decode(response);
        return KnownFirmware(Version.parse(text.trim()));
      } on Exception catch (e, stackTrace) {
        log('reading the firmware version failed', error: e, stackTrace: stackTrace);
        rethrow;
      }
    }
  `;
  expect(detect(write("lib/firmware_reader.dart", code))).toEqual([]);
});

test("stays quiet in a test asserting the throw", () => {
  const code = source`
    void main() {
      test('throws without a shell', () async {
        try {
          final result = await lister.processes();
          fail('should have thrown, got \$result');
        } on StateError catch (e, stackTrace) {
          // expected
        }
      });
    }
  `;
  expect(detect(write("test/process_lister_test.dart", code))).toEqual([]);
});

test("stays quiet on a wide try that is commented out", () => {
  const code = source`
    // try {
    //   final response = await connection.request(device, 'fw-version');
    //   return KnownFirmware(Version.parse(utf8.decode(response)));
    // } on FormatException {
    //   return const UnknownFirmware();
    // }
    void unused() {}
  `;
  expect(detect(write("lib/firmware_reader.dart", code))).toEqual([]);
});

const config = source`
  Future<Config> loadConfig(File file) async {
    try {
      final raw = await file.readAsString();
      return Config.fromJson(jsonDecode(raw));
    } on FormatException catch (e, stackTrace) {
      throw ConfigException(file.path);
    }
  }
`;

test("stays quiet when an edit only touches the handler of a wide try", () => {
  expect(detect(edit("lib/config_loader.dart", config, { written: "    throw ConfigException(file.path);" }))).toEqual([]);
});

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