MAD Lint 2.0
A comprehensive Dart/Flutter lint plugin that enforces best practices and catches common issues in your codebase.
Features
Code Quality Rules
- New Line Before Return: Ensures a blank line before return statements for better readability.
- No Magic Numbers: Catches usage of magic numbers in code.
- No Bang Operator: Prevents the use of the null assertion operator (
!). - Use Wildcard for Unused Parameters: Enforces using underscore (
_) for unused parameters in function declarations.
State Management Rules
-
Full Copy-With for State: Ensures all state classes have a complete
copyWithmethod implementation.- Detects missing
copyWithmethods in state classes. - Verifies all properties are included in
copyWithmethods.
- Detects missing
-
Mapped Fields Validation: Validates
mappedFieldsgetters in state classes.- Ensures
mappedFieldsgetter exists where required. - Validates that
mappedFieldsreturns aMap. - Ensures all fields are included in the mapping.
- Validates key-value pairs in the mapping.
- Ensures
Object Comparison & Equality
- Required Full Props: Ensures all properties are included in the
propsgetter when usingEquatable. This helps prevent bugs where properties might be accidentally omitted from the equality comparison.- Example:
// Good: class User extends Equatable { final String name; final int age; @override List<Object?> get props => [name, age]; // All fields included } // Will trigger the rule: class User extends Equatable { final String name; final int age; @override List<Object?> get props => [name]; // 'age' is missing }
- Example:
Resource Management
- Stream Subscription Disposal: Ensures proper disposal of
StreamSubscriptionobjects. - Ensure Dispose Called: Verifies that
disposemethods are called on objects that require cleanup.
Installation
Add the following to your analysis_options.yaml:
plugins:
mad_lint:
version: ^2.0.0
Configuration
You can enable/disable specific rules:
plugins:
mad_lint:
version: ^2.0.0
diagnostics:
stream_subscription_must_be_disposed: true
newline_before_return: true
required_full_props: true
ensure_dispose_called: true
no_magic_number: true
no_bang_operator: true
missing_copy_with_for_states: true
incomplete_copy_with_for_states: true
missing_mapped_fields_getter: true
mapped_fields_must_be_expression: true
mapped_fields_must_return_map: true
mapped_fields_not_all_fields: true
mapped_fields_key_value_mismatch: true
use_wildcard_for_unused_parameters: true
Migration from custom_lint to analysis_server_plugin
This guide describes how to migrate from custom_lint (and mad_lint) to the official Dart analyzer plugin system based on analysis_server_plugin.
The goal is to:
- Completely remove
dev_dep_common - Remove all mentions of
mad_lint - Stop using
custom_lint - Configure analyzer plugins according to the official documentation
1. Remove dev_dep_common and mad_lint
1.1 Delete the package
- Delete the package directory (e.g.
packages/dev_dep_common/) - Remove it from any workspace/monorepo tooling configuration (melos, scripts, etc.)
1.2 Remove all references
Search the entire repository and remove all references to:
dev_dep_commonmad_lint
Places to check:
pubspec.yaml(dependencies,dev_dependencies,dependency_overrides)analysis_options.yaml- CI scripts
- README and internal documentation
2. Remove custom_lint
In all packages where it was used:
2.1 Remove dependencies
Delete the following from pubspec.yaml:
custom_lintcustom_lint_builder- Any
*_lintpackages that were implemented specifically forcustom_lint
3. Configure analyzer plugins via analysis_options.yaml
Analyzer plugins are now configured directly in analysis_options.yaml.
If the plugin is published on pub.dev:
# analysis_options.yaml
plugins:
mad_lint: ^2.0.0
Libraries
- main
- rules/ensure_dispose_call/ensure_dispose_call
- rules/full_copy_with_for_state/full_copy_with_for_state
- rules/full_copy_with_for_state/incomplete_copy_with_rule
- rules/full_copy_with_for_state/missing_copy_with_rule
- rules/full_mapped_fields/full_mapped_fields
- rules/full_mapped_fields/mapped_fields_key_value_mismatch_rule
- rules/full_mapped_fields/mapped_fields_must_be_expression_rule
- rules/full_mapped_fields/mapped_fields_must_return_map_rule
- rules/full_mapped_fields/mapped_fields_not_all_fields_rule
- rules/full_mapped_fields/missing_mapped_fields_getter_rule
- rules/new_line_before_return
- rules/no_bang_operator_rule
- rules/no_magic_number_rule
- rules/required_full_props/required_full_props
- rules/rules
- rules/stream_subscription_must_be_disposed/stream_subscription_must_be_disposed
- rules/use_wildcard_for_unused_parameters_rule/use_wildcard_for_unused_parameters_rule
- utils/analyzer_extensions/ast_node_extension
- utils/analyzer_extensions/class_node_extension
- utils/analyzer_extensions/extensions
- utils/analyzer_extensions/function_body_extension
- utils/analyzer_extensions/token_extension
- utils/extensions_generic
- utils/source_range_extension
- utils/utils