throws
Annotations for documenting and enforcing throwing functions.
This package is the annotation layer. It works with:
- throws_plugin: analyzer plugin that enforces annotations and call handling.
- throws_collector: optional heuristic tool that can generate maps for external APIs to improve plugin accuracy.
Install
Add the dependency to your pubspec.yaml.
Usage
Annotate functions that can throw:
@Throws(reason: 'Parsing input failed', errors: {FormatException, RangeError})
int parsePositiveInt(String input) {
final value = int.parse(input);
if (value < 0) {
throw RangeError('Value must be non-negative');
}
return value;
}
You can also use the shorthand constant:
@throws
void mightThrow() {
throw Exception('x');
}
Expected errors
Use errors to declare the error types callers should handle. This is a set of Type literals.
@Throws(reason: 'Reason', errors: {StateError})
int singleValue(Iterable<int> values) => values.single;
Examples
Missing annotation
Bad (missing @Throws):
int parsePositiveInt(String input) {
final value = int.parse(input);
if (value < 0) {
throw RangeError('Value must be non-negative');
}
return value;
}
Good:
@Throws(reason: 'Parsing input failed', errors: {RangeError})
int parsePositiveInt(String input) {
final value = int.parse(input);
if (value < 0) {
throw RangeError('Value must be non-negative');
}
return value;
}
Calling a throwing function without handling
Bad (no try/catch and no @Throws on caller):
@Throws(reason: 'May throw', errors: {StateError})
int singleValue(Iterable<int> values) => values.single;
int readOne(Iterable<int> values) {
return singleValue(values);
}
Good (handle it):
@Throws(reason: 'May throw', errors: {StateError})
int singleValue(Iterable<int> values) => values.single;
int readOne(Iterable<int> values) {
try {
return singleValue(values);
} on StateError {
return -1;
}
}
Good (or declare it):
@Throws(reason: 'May throw', errors: {StateError})
int singleValue(Iterable<int> values) => values.single;
@Throws(reason: 'Pass-through', errors: {StateError})
int readOne(Iterable<int> values) => singleValue(values);
Annotation mismatch
Bad (declared errors do not match):
@Throws(reason: 'Wrong error set', errors: {ArgumentError})
void risky() {
throw StateError('boom');
}
Good:
@Throws(reason: 'Right error set', errors: {StateError})
void risky() {
throw StateError('boom');
}
How it all works together
- You annotate functions with @Throws or @throws.
- throws_plugin inspects your code and:
- Requires annotations on functions that throw.
- Requires try/catch or annotations when calling throwing functions.
- Validates that declared errors match what is thrown.
- throws_plugin can also read a throws.yaml file at your package root to learn about throwing members outside your package (SDK or dependencies).
- throws_collector can generate those maps, but it is optional and best-effort.
This package does not perform analysis itself. It only provides the annotations and shared types for the plugin.
Libraries
- throws
- Annotations for documenting throwing functions.