Awesome Lints

A comprehensive collection of custom lint rules for Dart and Flutter applications, built on top of the custom_lint package. These rules help you write cleaner, more maintainable, and bug-free code by catching common mistakes and enforcing best practices.

Features

  • 🎯 32 Flutter-specific lints - Catch Flutter widget issues, lifecycle problems, and performance pitfalls
  • πŸ” 65 Common Dart lints - General-purpose rules for any Dart codebase
  • πŸ“¦ 8 Provider-specific lints - Best practices for the Provider state management package
  • 🧊 22 Bloc-specific lints - Best practices for the Bloc state management package
  • ⏱️ 1 FakeAsync-specific lint - Catch common testing mistakes with fake_async
  • ⚑ Fast analysis - Built on custom_lint for efficient, real-time feedback
  • πŸ› οΈ Easy to configure - Flexible presets for different use cases, with optional customization
  • πŸ“š Well-documented - Every rule includes examples and explanations

Quick Start

Installation

  1. Add awesome_lints and custom_lint as dev dependencies:
dart pub add dev:awesome_lints
dart pub add dev:custom_lint
  1. Configure analysis_options.yaml with a preset:
analyzer:
  plugins:
    - custom_lint

# Choose a preset (recommended for most projects):
include: package:awesome_lints/presets/recommended.yaml
  1. Run the linter:
# Analyze your project
dart run custom_lint

# Or with auto-fix support (where available)
dart run custom_lint --fix

Usage in IDE

VS Code: Install the Dart extension - custom_lint diagnostics will appear automatically.

Android Studio / IntelliJ: Custom lint diagnostics will appear in the editor alongside standard Dart analysis.

Watch Mode: For continuous analysis during development:

dart run custom_lint --watch

Available Lints

Flutter-Specific Rules

32 rules designed specifically for Flutter applications, covering:

  • Widget lifecycle and state management
  • Performance optimization
  • Common Flutter anti-patterns
  • Resource disposal
  • Builder patterns and best practices

πŸ“– View all Flutter lints β†’

Popular rules include:

  • avoid-late-context - Prevents context usage in late field initializers
  • avoid-mounted-in-setstate - Ensures proper mounted checks
  • prefer-spacing - Use Flutter 3.27+ spacing parameter
  • pass-existing-future-to-future-builder - Prevents future recreation on rebuild
  • prefer-container - Suggests simplifying nested widgets

Common Dart Rules

65 rules applicable to any Dart codebase, covering:

  • Code quality and maintainability
  • Logic errors and potential bugs
  • Performance considerations
  • Code style and consistency
  • Null safety best practices

πŸ“– View all Common lints β†’

Popular rules include:

  • avoid-non-null-assertion - Warns about unsafe ! operator usage
  • arguments-ordering - Enforces parameter order consistency
  • no-equal-then-else - Detects identical if/else branches
  • avoid-collection-equality-checks - Prevents identity vs value equality bugs
  • no-magic-number - Requires named constants for numeric literals

Provider Rules

8 rules designed specifically for applications using the Provider package:

  • Provider usage patterns and best practices
  • Memory leak prevention
  • Correctness checks for read/watch usage
  • Code maintainability improvements

πŸ“– View all Provider lints β†’

Popular rules include:

  • avoid-read-inside-build - Prevents read() usage in build methods
  • avoid-watch-outside-build - Ensures watch() is only used in build
  • dispose-providers - Checks for proper resource disposal
  • prefer-multi-provider - Suggests MultiProvider over nested providers
  • prefer-provider-extensions - Prefers context.read/watch over Provider.of

Bloc Rules

22 rules designed specifically for applications using the Bloc package:

  • Bloc/Cubit usage patterns and best practices
  • Encapsulation and architectural correctness
  • Event and state management
  • Memory leak prevention
  • Immutability enforcement

πŸ“– View all Bloc lints β†’

Popular rules include:

  • avoid-bloc-public-fields - Enforces private fields in Blocs/Cubits
  • avoid-bloc-public-methods - Prevents public methods except overrides
  • avoid-passing-build-context-to-blocs - Prevents BuildContext coupling
  • prefer-immutable-bloc-events - Requires @immutable on event classes
  • prefer-sealed-bloc-state - Requires sealed/final modifiers on state classes

FakeAsync Rules

1 rule designed specifically for applications using the fake_async package for testing:

  • Correctness checks for FakeAsync usage
  • Prevent tests from always passing
  • Ensure proper async testing patterns

πŸ“– View all FakeAsync lints β†’

Rules include:

  • avoid-async-callback-in-fake-async - Prevents async callbacks in FakeAsync that aren't awaited

Configuration

awesome_lints provides preset configurations for different use cases:

Preset Rules Use Case
core.yaml ~15 Essential bug prevention only
recommended.yaml ~40 Balanced set (recommended for most projects)
strict.yaml 128 All rules (comprehensive analysis)
Category-specific Varies flutter.yaml, common.yaml, provider.yaml, bloc.yaml, fake_async.yaml

Quick Start (Recommended):

# analysis_options.yaml
include: package:awesome_lints/presets/recommended.yaml

Maintain v2.0.0 Behavior (All Rules):

# analysis_options.yaml
include: package:awesome_lints/presets/strict.yaml

Gradual Adoption (Core Rules Only):

# analysis_options.yaml
include: package:awesome_lints/presets/core.yaml

Custom Configuration

You can extend presets and customize rules:

# Start with recommended preset
include: package:awesome_lints/presets/recommended.yaml

custom_lint:
  rules:
    # Enable additional rules
    - no_magic_number:
        allowed_numbers: [0, 1, -1, 100]
    - prefer_switch_expression

    # Disable specific rules from the preset
    - avoid_barrel_files: false

Enabling Individual Rules

Starting from a preset and adding specific rules:

# analysis_options.yaml
include: package:awesome_lints/presets/core.yaml

custom_lint:
  rules:
    # Enable additional rules not in the core preset
    - no_magic_number:
        allowed_numbers: [0, 1, -1, 100]
    - prefer_switch_expression
    - avoid_barrel_files

Starting from scratch (no preset):

# analysis_options.yaml
analyzer:
  plugins:
    - custom_lint

custom_lint:
  enable_all_lint_rules: false
  rules:
    # List only the rules you want
    - avoid_non_null_assertion
    - no_magic_number
    - avoid_late_context
    - arguments_ordering
    - prefer_early_return

Disabling specific rules from a preset:

# analysis_options.yaml
include: package:awesome_lints/presets/recommended.yaml

custom_lint:
  rules:
    # Disable unwanted rules by setting them to false
    - avoid_barrel_files: false
    - no_magic_string: false

πŸ’‘ Tip: Browse the category documentation files to discover available rules:

Development

Project Structure

awesome_lints/
β”œβ”€β”€ lib/
β”‚   └── src/
β”‚       β”œβ”€β”€ lints/
β”‚       β”‚   β”œβ”€β”€ flutter/           # Flutter-specific lints
β”‚       β”‚   β”‚   β”œβ”€β”€ FLUTTER_LINTS.md
β”‚       β”‚   β”‚   └── *.dart
β”‚       β”‚   β”œβ”€β”€ common/            # Common Dart lints
β”‚       β”‚   β”‚   β”œβ”€β”€ COMMON_LINTS.md
β”‚       β”‚   β”‚   └── *.dart
β”‚       β”‚   β”œβ”€β”€ provider/          # Provider-specific lints
β”‚       β”‚   β”‚   β”œβ”€β”€ PROVIDER_LINTS.md
β”‚       β”‚   β”‚   └── *.dart
β”‚       β”‚   β”œβ”€β”€ bloc/              # Bloc-specific lints
β”‚       β”‚   β”‚   β”œβ”€β”€ BLOC_LINTS.md
β”‚       β”‚   β”‚   └── *.dart
β”‚       β”‚   └── fake_async/        # FakeAsync-specific lints
β”‚       β”‚       β”œβ”€β”€ FAKE_ASYNC_LINTS.md
β”‚       β”‚       └── *.dart
β”‚       └── awesome_lints_plugin.dart
β”œβ”€β”€ test/
β”‚   └── fixtures/
β”‚       └── test_project/          # Test cases for all rules
└── README.md

Adding a New Lint Rule

  1. Create the rule file:

    • For Flutter rules: lib/src/lints/flutter/your_rule_name.dart
    • For common rules: lib/src/lints/common/your_rule_name.dart
    • For Provider rules: lib/src/lints/provider/your_rule_name.dart
    • For Bloc rules: lib/src/lints/bloc/your_rule_name.dart
    • For FakeAsync rules: lib/src/lints/fake_async/your_rule_name.dart
  2. Implement the DartLintRule class:

import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

class YourRuleName extends DartLintRule {
  const YourRuleName() : super(code: _code);

  static const _code = LintCode(
    name: 'your_rule_name',
    problemMessage: 'Description of the problem',
    correctionMessage: 'How to fix it',
    errorSeverity: DiagnosticSeverity.WARNING,
  );

  @override
  void run(
    CustomLintResolver resolver,
    DiagnosticReporter reporter,
    CustomLintContext context,
  ) {
    // Your lint logic here
  }
}
  1. Register the rule:

    • Add export to lib/src/lints/flutter/flutter.dart, lib/src/lints/common/common.dart, lib/src/lints/provider/provider.dart, lib/src/lints/bloc/bloc.dart, or lib/src/lints/fake_async/fake_async.dart
    • Add the rule instance in lib/src/awesome_lints_plugin.dart
  2. Create test fixtures:

test/fixtures/test_project/lib/your_rule_name/
β”œβ”€β”€ should_trigger_lint.dart       # Use // expect_lint: your_rule_name
└── should_not_trigger_lint.dart   # Valid code that shouldn't trigger
  1. Document the rule:
    • Add entry to FLUTTER_LINTS.md, COMMON_LINTS.md, PROVIDER_LINTS.md, BLOC_LINTS.md, or FAKE_ASYNC_LINTS.md
    • Include "Why?", "Bad", and "Good" examples

Running Tests

# Navigate to test project
cd test/fixtures/test_project

# Install dependencies
flutter pub get

# Run the linter (this validates all test fixtures)
dart run custom_lint

Expected output: Lints should only appear on lines marked with // expect_lint: rule_name.

Testing Locally

To test your rules in a real project:

# In your test project's pubspec.yaml
dev_dependencies:
  awesome_lints:
    path: /absolute/path/to/awesome_lints
  custom_lint: ^0.7.0

Requirements

  • Dart SDK: 3.10.0 or higher
  • Flutter SDK: 3.0.0 or higher (for Flutter-specific rules)
  • custom_lint: ^0.7.0

Contributing

Contributions are welcome! When submitting new rules:

  1. Ensure the rule catches real-world problems or enforces valuable best practices
  2. Provide clear documentation with examples
  3. Include comprehensive test fixtures
  4. Follow the existing code structure and style

Documentation Templates

To maintain consistency across project documentation, use the templates in doc/templates/:

See doc/templates/README.md for detailed usage instructions and doc/templates/QUICK_START.md for a quick reference.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Resources

Acknowledgments

Built with custom_lint by Invertase.

Libraries

awesome_lints
Comprehensive custom lint rules for Dart and Flutter applications.