Throws Lints

Custom lint rules that enforce proper exception documentation through @throws annotations in your Dart code. This package helps maintain consistent exception handling documentation and makes it easier to identify which functions can throw exceptions.

Features

This package provides three complementary lint rules:

  1. missing_throws_annotation - Ensures functions that throw exceptions directly are annotated with @throws
  2. throwing_function_calls_require_throws - Ensures functions calling other @throws functions are also annotated
  3. unnecessary_throws_annotation - Prevents using @throws on functions that don't actually throw

Additionally, the package exports the @throws annotation that you can use in your code.

Why Use This Package?

  • Better Documentation: Clearly identify which functions can throw exceptions
  • Safer Code: Know when you need to handle exceptions when calling functions
  • Consistent Codebase: Enforce exception documentation standards across your team
  • Catch Mistakes: Prevent forgetting to annotate throwing functions or using incorrect annotations

Installation

Enable the lints in your analysis_options.yaml:

plugins:
  throws_lints: ^1.0.0

Optional

Add throws_lints to your pubspec.yaml if you want to use @throws annotation directly from the package:

dependencies:
  throws_lints: ^1.0.0

Usage

Import the Annotation

import 'package:throws_lints/throws_lints.dart';

Rule 1: missing_throws_annotation

Functions that throw exceptions directly must have the @throws annotation.

// ❌ BAD - Missing @throws annotation
void riskyOperation() {
  throw Exception('Something went wrong');
}

// ✅ GOOD - Properly annotated
@throws
void riskyOperation() {
  throw Exception('Something went wrong');
}

// Also applies to rethrow
@throws
void handleError() {
  try {
    riskyOperation();
  } catch (e) {
    rethrow; // Must have @throws
  }
}

Rule 2: throwing_function_calls_require_throws

Functions that call other @throws functions must also have the annotation (unless they catch the exception).

@throws
void databaseOperation() {
  throw Exception('DB error');
}

// ❌ BAD - Calls throwing function without annotation
void saveData() {
  databaseOperation(); // Can throw!
}

// ✅ GOOD - Has @throws annotation
@throws
void saveData() {
  databaseOperation();
}

// ✅ GOOD - Catches the exception, no annotation needed
void saveDataSafely() {
  try {
    databaseOperation();
  } catch (e) {
    print('Save failed: $e');
  }
}

Rule 3: unnecessary_throws_annotation

Don't use @throws on functions that don't actually throw.

// ❌ BAD - Has @throws but doesn't throw
@throws
void safeFunction() {
  print('This is safe');
}

// ✅ GOOD - No annotation for safe functions
void safeFunction() {
  print('This is safe');
}

// ❌ BAD - All exceptions are caught internally
@throws
void allCaught() {
  try {
    throw Exception('Caught');
  } catch (e) {
    print('Handled: $e');
  }
}

Try-Catch Handling

The lints are smart about try-catch blocks:

@throws
void throwingFunction() {
  throw Exception('Error');
}

// ✅ No annotation needed - exception is caught
void safelyCalls() {
  try {
    throwingFunction();
  } catch (e) {
    print('Caught: $e');
  }
}

// ❌ Needs @throws - exception in finally can propagate
void finallyThrows() {
  try {
    print('Safe');
  } finally {
    throwingFunction(); // Not caught!
  }
}

Additional Information

For more examples, see the example directory.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

This package is licensed under the MIT License.

Libraries

main
throws_lints
Lint rules for enforcing @throws annotation usage in Dart code.