many_lints 1.1.0
many_lints: ^1.1.0 copied to clipboard
A comprehensive collection of custom lint rules, quick fixes, and code assists for Flutter and Dart projects.
many_lints Examples #
This directory contains example code demonstrating every lint rule provided by many_lints. Each file in lib/ corresponds to one rule and marks the relevant bad and good cases. Most files trigger their named lint directly; the two path-based rules (match_lib_folder_structure and prefer_correct_test_file_name) use commented path examples because a flat lib/ file cannot violate either rule. Since the broad example preset is enabled, dart analyze example can also show related diagnostics from other rules.
Setup #
Add to your analysis_options.yaml:
plugins:
many_lints: ^1.1.0
Excluding paths per rule #
many_lints.yaml in this directory demonstrates per-rule exclude:
rules:
avoid_only_rethrow:
exclude:
- lib/excluded/**
lib/excluded/excluded_example.dart contains the
same redundant catch clauses as lib/avoid_only_rethrow_example.dart,
but reports nothing — that path is excluded for the rule. Delete many_lints.yaml and
run dart analyze again to see the two diagnostics come back.
Note that avoid_commented_out_code does still report in that file. Each exclude
sits under one rule and affects only that rule — excluding a path from
avoid_only_rethrow says nothing about the other rules. To skip a path for several
rules, give each of them its own exclude.
Paths are globs, but a plain path works too — lib/generated/foo.dart is a valid
pattern, and you can list as many entries as you like:
rules:
avoid_only_rethrow:
exclude:
- lib/legacy/parser.dart # one specific file
- lib/generated/** # a whole directory tree
- "**/*.g.dart" # every generated file
The same rules: block can instead live under a top-level many_lints: key in
analysis_options.yaml — the two forms are equivalent.
All Rules #
| Rule | Description | Fix |
|---|---|---|
always_pass_global_key |
Don't create a GlobalKey inside build. | — |
always_remove_listener |
Ensure every addListener() has a matching removeListener() in dispose(). | Yes |
arguments_ordering |
Keep named arguments in a configured order. | — |
async_value_nullable_pattern |
Matching AsyncValue(:final value?) on a nullable value hides a legitimate null result. | Yes |
avoid_accessing_collections_by_constant_index |
Avoid accessing a collection by a constant index inside a loop. | — |
avoid_accessing_other_classes_private_members |
Make the underscore mean what everyone reads it as. | — |
avoid_ad_hoc_left_type |
A pipeline only composes when every step shares one error type. | — |
avoid_banned_annotations |
Ban specific annotations, optionally scoped by directory. | — |
avoid_banned_exports |
Ban re-exports of specific libraries, optionally scoped by directory. | — |
avoid_banned_imports |
Ban imports of specific libraries, optionally scoped by directory. | — |
avoid_banned_names |
Ban specific identifiers from being used as declaration names. | — |
avoid_banned_types |
Ban specific types from being named, optionally scoped by directory. | — |
avoid_bare_await_in_do |
Awaiting a raw Future inside a Do block escapes the block's tracking. | — |
avoid_bloc_public_methods |
Prevent public methods, getters, and setters in Bloc classes. | — |
avoid_border_all |
Use Border.fromBorderSide instead of Border.all for const support. | Yes |
avoid_build_context_in_providers |
Providers outlive widgets, so they should not receive a BuildContext. | — |
avoid_cascade_after_if_null |
Detect cascades after if-null operators without parentheses. | Yes |
avoid_catch_error |
Use try/catch instead of Future.catchError. | — |
avoid_collapsible_if |
Merge nested if statements with &&. | Yes |
avoid_collection_equality_checks |
Avoid comparing collections with == or != as it checks reference equality, not contents. | — |
avoid_collection_methods_with_unrelated_types |
Avoid calling collection methods with arguments whose types are unrelated to the collection's type parameter. | — |
avoid_commented_out_code |
Detect and flag commented-out code. | Yes |
avoid_complex_conditions |
Keep boolean conditions within an operand budget. | — |
avoid_conditional_hooks |
Never call hooks inside conditionals, loops, or ternaries. | — |
avoid_constant_conditions |
Detect comparisons where both sides are constants. | — |
avoid_constant_switches |
Detect switch statements on constant expressions. | — |
avoid_contradictory_expressions |
Detect logical AND conditions that always evaluate to false. | — |
avoid_deep_nesting |
Keep control flow within a nesting budget. | — |
avoid_deep_widget_nesting |
Keep a widget tree within a nesting budget. | — |
avoid_default_tostring |
Don't interpolate objects that don't override toString. | — |
avoid_dollar_outside_do_frame |
Calling a Do block's extraction function from a nested callback unwinds through code that cannot handle it. | — |
avoid_dst_unsafe_date_arithmetic |
Calendar day arithmetic on a local DateTime should not go through Duration. | Yes |
avoid_duplicate_bloc_event_handlers |
Register each bloc event type exactly once. | — |
avoid_duplicate_cascades |
Detect duplicate cascade sections in cascade expressions. | Yes |
avoid_duplicate_collection_elements |
Don't repeat the same element in a collection literal. | Yes |
avoid_duplicate_mixins |
Flag a mixin applied twice in one with clause. |
— |
avoid_either_of_future |
A Future nested in Either or Option escapes the error channel. | — |
avoid_empty_catch |
Detect catch clauses that silently discard the failure. | — |
avoid_empty_setstate |
Don't call setState with an empty callback. | — |
avoid_empty_spread |
Remove spreads of empty collection literals. | Yes |
avoid_equal_expressions |
Both operands of a binary expression should not be identical. | — |
avoid_exit_outside_entrypoint |
Detect exit() outside the program entrypoint, which kills tests. | — |
avoid_expanded_as_spacer |
Use Spacer instead of Expanded with an empty child. | Yes |
avoid_flexible_outside_flex |
Only use Flexible and Expanded as direct children of Row, Column, or Flex. | — |
avoid_focused_tests |
Detect tests focused with solo:, which silences their siblings. | — |
avoid_future_ignore |
Do not silently suppress Future errors with an unexplained ignore call. | — |
avoid_future_of_either |
Future<Either> throws away the composition TaskEither already gives you. | — |
avoid_future_of_option |
Future<Option> throws away the composition TaskOption already gives you. | — |
avoid_generics_shadowing |
Avoid generic type parameters that shadow top-level declarations. | Yes |
avoid_get_or_else_swallowing_failure |
getOrElse is handed the failure; ignoring it should be a visible decision. | — |
avoid_high_cyclomatic_complexity |
Keep a function within a complexity budget. | — |
avoid_hooks_outside_build |
Only call hooks from a hook context. | — |
avoid_incomplete_copy_with |
Ensure copyWith methods include all constructor parameters. | Yes |
avoid_inconsistent_digit_separators |
Group digit separators at a regular interval. | Yes |
avoid_incorrect_image_opacity |
Use Image's opacity parameter instead of wrapping in Opacity. | Yes |
avoid_inherited_widget_in_initstate |
Don't look up inherited widgets inside initState. | — |
avoid_inverted_boolean_checks |
Use the opposite operator instead of negating a comparison. | Yes |
avoid_late_context |
Don't read BuildContext in a late field initializer. | — |
avoid_late_final_reassignment |
Flag a late final field assigned twice on one path. |
— |
avoid_long_files |
Keep a file within a line budget. | — |
avoid_long_functions |
Keep function bodies within a line budget. | — |
avoid_long_parameter_list |
Keep parameter lists within a budget. | — |
avoid_map_keys_contains |
Use containsKey() instead of .keys.contains() for better performance. | Yes |
avoid_missing_completer_stack_trace |
Pass the stack trace to Completer.completeError. | — |
avoid_missing_enum_constant_in_map |
Cover every enum constant in a map keyed by that enum. | — |
avoid_misused_hooks |
Don't call hooks inside loops. | — |
avoid_misused_test_matchers |
Detect test matchers used with incompatible value types. | — |
avoid_mounted_in_setstate |
Detect mounted checks inside setState callbacks. | — |
avoid_negated_conditions |
State the positive case first in an if/else. | Yes |
avoid_nested_conditional_expressions |
Flag a conditional nested inside another. | — |
avoid_nested_do_notation |
A nested Do block short-circuits on its own instead of failing the outer pipeline. | — |
avoid_nested_futures |
Don't declare Future<Future<T>>. | — |
avoid_nested_shorthands |
Avoid nesting a dot shorthand inside another dot shorthand invocation. | — |
avoid_non_null_assertion |
Don't assert away null with the ! operator. | — |
avoid_not_encodable_in_to_json |
Don't put values jsonEncode cannot serialize into a toJson map. | — |
avoid_notifier_constructors |
Prevent initialization logic in Notifier constructors. | Yes |
avoid_only_rethrow |
Detect catch clauses that only rethrow the exception. | Yes |
avoid_passing_async_when_sync_expected |
Don't pass an async closure where a void-returning function is expected. | — |
avoid_passing_bloc_to_bloc |
Prevent Bloc/Cubit classes from depending on other Bloc/Cubit instances. | — |
avoid_passing_build_context_to_blocs |
Prevent passing BuildContext to Bloc or Cubit classes. | — |
avoid_public_notifier_properties |
Prevent public fields, getters, and setters on Notifier classes. | — |
avoid_recursive_widget_calls |
Don't build a widget from inside its own build method. | — |
avoid_redundant_async |
Flag an async function that never awaits. | — |
avoid_redundant_else |
Drop the else when the if branch always exits. | Yes |
avoid_ref_inside_state_dispose |
Avoid accessing ref inside the dispose method of a ConsumerState. | — |
avoid_ref_read_inside_build |
Subscribe in build; do not read once. | Yes |
avoid_ref_watch_outside_build |
Subscribe only in build; read once everywhere else. | — |
avoid_removed_fpdart_api |
Names removed in fpdart 1.0.0, with the replacement to use. | — |
avoid_returning_widgets |
Extract widget helper methods into separate widget classes. | — |
avoid_self_compare |
Flag a value compared against itself with compareTo. | — |
avoid_shadowed_extension_methods |
An extension member the extended type already has. | — |
avoid_shrink_wrap_in_lists |
Avoid using shrinkWrap in ListView for better scroll performance. | Yes |
avoid_single_child_in_multi_child_widgets |
Don't use Column, Row, or other multi-child widgets with only one child. | — |
avoid_single_field_destructuring |
Avoid destructuring a single field when direct property access is simpler. | Yes |
avoid_skipped_tests |
Detect tests, groups and libraries switched off in place. | — |
avoid_state_constructors |
Avoid constructors with logic in State classes. | Yes |
avoid_throw_in_catch_block |
Detect throw expressions inside catch blocks. | Yes |
avoid_throw_in_fp_callback |
A throw inside an fpdart callback escapes the error channel the pipeline is built to carry. | — |
avoid_todo_comments |
Detect TODO comments that reference no tracked issue. | — |
avoid_too_many_methods |
Keep a class within a method budget. | — |
avoid_too_many_widgets_per_build |
Keep one build method within a widget budget. | — |
avoid_unassigned_stream_subscriptions |
Ensure stream subscriptions are assigned to a variable for proper cancellation. | — |
avoid_unmodified_loop_condition |
A while loop whose condition the body can never change. | — |
avoid_unnecessary_call |
Invoke a function directly instead of through .call(). | — |
avoid_unnecessary_constructor |
Remove a constructor identical to the default one. | — |
avoid_unnecessary_consumer_widgets |
Don't extend ConsumerWidget if you never use WidgetRef. | Yes |
avoid_unnecessary_continue |
Remove a continue that ends a loop body. |
Yes |
avoid_unnecessary_enum_prefix |
Drop an enum name repeated in its own constants. | — |
avoid_unnecessary_extends |
Remove an explicit extends Object. |
— |
avoid_unnecessary_gesture_detector |
Remove GestureDetector widgets that have no event handlers. | Yes |
avoid_unnecessary_hook_widgets |
Don't extend HookWidget if you never call any hooks. | Yes |
avoid_unnecessary_negations |
Collapse double negations. | Yes |
avoid_unnecessary_option |
An Option that is wrapped and immediately unwrapped earns nothing. | — |
avoid_unnecessary_overrides |
Detect overrides that only delegate to super. | Yes |
avoid_unnecessary_return |
Remove a bare return; that ends a void function. |
— |
avoid_unnecessary_setstate |
Detect unnecessary setState calls in lifecycle methods. | Yes |
avoid_unnecessary_stateful_widgets |
Detect StatefulWidgets that have no mutable state. | Yes |
avoid_unrelated_type_casts |
Don't cast or type-test between unrelated types. | — |
avoid_unremovable_callbacks_in_listeners |
Don't pass an inline closure to addListener. | — |
avoid_unrun_task |
Discarding a lazy fpdart value silently skips the work it describes. | — |
avoid_unsafe_collection_methods |
Check for emptiness before using first, last, single or reduce. | — |
avoid_untyped_safe_cast |
safeCast without explicit type arguments infers dynamic and always succeeds. | — |
avoid_unused_after_null_check |
A variable null-checked but never used in the guarded branch. | — |
avoid_wildcard_cases_with_enums |
Keep exhaustiveness checking by listing enum cases explicitly. | — |
avoid_wrapping_in_padding |
Avoid wrapping widgets that support padding in a Padding widget. | Yes |
banned_usage |
Ban specific members, such as DateTime.now, optionally scoped by directory. | — |
check_for_equals_in_render_object_setters |
Compare before marking a RenderObject dirty. | — |
check_is_not_closed_after_async_gap |
Check isClosed before emitting state after an await. | — |
dispose_fields |
Ensure State fields with disposal methods are cleaned up in dispose(). | Yes |
dispose_provided_instances |
Ensure disposable instances in Riverpod providers are cleaned up with ref.onDispose. | Yes |
double_literal_format |
Write double literals with exactly one leading zero and no redundant trailing zeros. | Yes |
emit_new_bloc_state_instances |
Emit a new state instance instead of the existing state object. | — |
enum_constants_ordering |
Keep enum constants in a configured order. | — |
format_comment |
Write comments as capitalised, terminated sentences. | — |
format_test_name |
Hold test descriptions to a house pattern. | — |
function_always_returns_null |
A nullable-returning function whose every path returns null. | — |
function_always_returns_same_value |
Flag a function whose every return yields the same constant. | — |
handle_bloc_event_subclasses |
Register a handler for every Bloc event subclass. | — |
initializers_ordering |
Keep constructor initializers in field order. | — |
list_all_equatable_fields |
Ensure all fields are listed in Equatable props. | Yes |
map_keys_ordering |
Keep map literal keys in a configured order. | — |
match_class_name_pattern |
Match class names against a regular expression. | — |
match_getter_setter_field_names |
Make a getter and setter pair use the same field. | — |
match_lib_folder_structure |
Keep folders under lib/ in lower_snake_case. | — |
max_imports |
Keep a file within an import budget. | — |
max_statements |
Keep a function within a statement budget. | — |
member_ordering |
Keep class members in a configured order. | — |
missing_provider_scope |
Flutter applications using Riverpod must have a ProviderScope at the root of the widget tree. | Yes |
never_discard_build_context |
Don't discard a BuildContext parameter with a wildcard. | Yes |
no_equal_conditions |
Flag an if/else-if chain that repeats a condition. | — |
no_equal_switch_case |
Flag two switch branches with identical bodies. | — |
no_equal_then_else |
Both branches of a condition are identical. | — |
no_magic_number |
Give a number a name when it carries a policy. | — |
no_magic_string |
Name a string once it is repeated. | — |
notifier_build |
Classes annotated with @riverpod must define a build method. | Yes |
parameters_ordering |
Keep named parameters in a configured order. | — |
pass_existing_future_to_future_builder |
Don't create a new Future inline inside FutureBuilder. | — |
pass_existing_stream_to_stream_builder |
Don't create a new Stream inline inside StreamBuilder. | — |
pattern_fields_ordering |
Keep pattern fields in a configured order. | — |
prefer_abstract_final_static_class |
Classes with only static members should be declared as abstract final. | Yes |
prefer_add_all |
Replace an add-only loop with addAll. | Yes |
prefer_align_over_container |
Use Align instead of Container when only alignment is set. | Yes |
prefer_any_or_every |
Use .any() or .every() instead of .where().isEmpty/.isNotEmpty. | Yes |
prefer_async_callback |
Use 'AsyncCallback' instead of 'Future<void> Function()'. | Yes |
prefer_bloc_extensions |
Use context.read/watch instead of BlocProvider.of or RepositoryProvider.of. | Yes |
prefer_boolean_prefixes |
Name booleans as questions. | — |
prefer_center_over_align |
Use Center instead of Align when alignment is center. | Yes |
prefer_chain_either |
chainEither lifts a synchronous Either step for you. | — |
prefer_chaining_over_intermediate_run |
Several .run() calls in one body are a chain that was never joined up. | — |
prefer_class_destructuring |
Use Dart 3 class destructuring when accessing multiple properties on the same object. | Yes |
prefer_compute_over_isolate_run |
Use 'compute()' instead of 'Isolate.run()' for web platform compatibility. | Yes |
prefer_conditional_expressions |
Collapse a two-way if/else into a conditional expression. | — |
prefer_const_border_radius |
Use BorderRadius.all(Radius.circular()) for const support. | Yes |
prefer_constrained_box_over_container |
Use ConstrainedBox instead of Container when only constraints is set. | Yes |
prefer_container |
Replace sequences of nested widgets with a single Container. | Yes |
prefer_correct_callback_field_name |
Name callbacks onSomething, the way Flutter does. | — |
prefer_correct_edge_insets_constructor |
Use the simplest EdgeInsets constructor for the given values. | Yes |
prefer_correct_error_name |
Name exception and error classes with the matching suffix. | — |
prefer_correct_future_return_type |
Expose async results as non-nullable Future values. | Yes |
prefer_correct_handler_name |
Name event handlers after the event they answer. | — |
prefer_correct_identifier_length |
Keep identifier length within bounds. | — |
prefer_correct_json_casts |
Cast JSON values to nullable types. | — |
prefer_correct_setter_parameter_name |
Use one parameter name in every setter. | — |
prefer_correct_test_file_name |
Name test files so the runner actually runs them. | — |
prefer_correct_type_name |
Keep type names within a sensible length and correctly capitalised. | — |
prefer_declaring_const_constructor |
Declare a const constructor where the class allows one. | — |
prefer_do_notation |
Deeply nested flatMap callbacks read flatter as a Do block. | — |
prefer_early_return |
Replace a body-wrapping if with an early-return guard. | Yes |
prefer_enums_by_name |
Use .byName() instead of .firstWhere() to look up enum values by name. | Yes |
prefer_equatable_mixin |
Prefer using EquatableMixin instead of extending Equatable. | Yes |
prefer_expect_later |
Use 'expectLater' instead of 'expect' when testing Futures. | Yes |
prefer_explicit_function_type |
Prefer explicit function type annotations over the bare 'Function' type. | Yes |
prefer_explicit_parameter_names |
Name the parameters of a function type. | — |
prefer_explicit_type_arguments |
Pin the type arguments of the APIs where inference surprises. | — |
prefer_extracting_callbacks |
Keep long callbacks out of the widget tree. | — |
prefer_for_loop_in_children |
Prefer collection-for syntax over functional list building in widget children. | Yes |
prefer_from_nullable |
A null check that builds an Option by hand is what Option.fromNullable is for. | Yes |
prefer_from_predicate |
A conditional guarding an Option is one Option.fromPredicate call. | Yes |
prefer_getter_over_method |
Make a no-argument value read a getter. | — |
prefer_immediate_return |
Return an expression directly instead of via a throwaway variable. | Yes |
prefer_immutable_bloc_state |
Ensure Bloc and Cubit state classes are annotated with @immutable. | Yes |
prefer_immutable_state |
Ensure classes named as state are annotated with @immutable. | Yes |
prefer_iterable_of |
Use List.of() / Set.of() instead of .from() for type-safe copies. | Yes |
prefer_match_file_name |
Name a file after the first public declaration in it. | — |
prefer_moving_to_variable |
Compute a repeated property or invocation chain once into a variable. | — |
prefer_multi_bloc_provider |
Use MultiBlocProvider, MultiBlocListener, or MultiRepositoryProvider instead of nesting. | Yes |
prefer_named_parameters |
Name parameters once there are more than a couple. | — |
prefer_overriding_parent_equality |
Override == and hashCode when the parent class overrides them. | Yes |
prefer_padding_over_container |
Use Padding instead of Container when only padding or margin is set. | Yes |
prefer_prefixed_global_constants |
Prefix public top-level constants. | — |
prefer_primary_constructors |
Prefer a primary constructor (Dart 3.13+) over a class of final fields plus a field-assigning constructor. | Yes |
prefer_private_named_parameters |
Prefer private named parameters (Dart 3.12+) over initializer-list boilerplate. | Yes |
prefer_return_await |
Detect missing await on returned Futures inside try-catch. | Yes |
prefer_returning_condition |
Return the condition instead of true/false branches. | — |
prefer_returning_shorthands |
Use dot shorthand constructors in expression function return values. | Yes |
prefer_safe_collection_access |
list.first throws where list.head returns None. | Yes |
prefer_shorthands_with_constructors |
Use dot shorthand constructors for common Flutter classes. | Yes |
prefer_shorthands_with_enums |
Use dot shorthands instead of explicit enum prefixes. | Yes |
prefer_shorthands_with_static_fields |
Use dot shorthands instead of explicit class prefixes for static fields. | Yes |
prefer_simpler_patterns_null_check |
Suggest simpler null-check patterns in if-case expressions. | Yes |
prefer_single_declaration_per_file |
Keep one top-level declaration per file, with per-type budgets. | — |
prefer_single_setstate |
Merge multiple setState calls into a single call. | Yes |
prefer_single_widget_per_file |
Keep one public widget per file for better organization. | — |
prefer_sized_box_square |
Use SizedBox.square when width and height are equal. | Yes |
prefer_spacing |
Use the spacing argument on Row/Column instead of SizedBox spacers. | — |
prefer_string_parse_extensions |
Option.fromNullable(int.tryParse(s)) is what toIntOption already is. | Yes |
prefer_switch_expression |
Suggest converting switch statements to switch expressions. | Yes |
prefer_switch_with_enums |
Use a switch instead of an if-else chain over enum constants. | — |
prefer_task_either_over_try_catch |
A repository's failures belong in its signature, not in a try/catch. | — |
prefer_test_matchers |
Prefer using a Matcher instead of a literal value in expect(). | — |
prefer_text_rich |
Use Text.rich instead of RichText for better accessibility. | Yes |
prefer_theme_mode_getters |
Prefer ThemeMode.isDark/isLight/isSystem getters (Flutter 3.44+) over == comparisons. | Yes |
prefer_transform_over_container |
Use Transform instead of Container when only transform is set. | Yes |
prefer_type_over_var |
Prefer an explicit type annotation over 'var'. | Yes |
prefer_typed_exceptions |
Detect throws that give callers nothing to catch selectively. | — |
prefer_typedefs_for_callbacks |
Name a multi-parameter function type with a typedef. | — |
prefer_unit_over_void |
void is not a value, so an fpdart type parameterised with it stops composing. | Yes |
prefer_use_callback |
Use 'useCallback' instead of 'useMemoized' for memoizing functions. | Yes |
prefer_use_prefix |
Custom hooks should start with the 'use' prefix. | Yes |
prefer_void_callback |
Use 'VoidCallback' instead of 'void Function()'. | Yes |
prefer_widget_private_members |
A widget's public API is its constructor. | — |
prefer_wildcard_pattern |
Use the wildcard pattern '_' instead of 'Object()' for catch-all cases. | Yes |
proper_super_calls |
Enforce correct ordering of super lifecycle calls in State classes. | Yes |
protected_notifier_properties |
A Notifier's state, ref and future should not be used from outside the notifier. | — |
provider_parameters |
Family provider arguments must have stable equality, or the provider is recreated on every rebuild. | — |
record_fields_ordering |
Keep record named fields in a configured order. | — |
require_atomic_async_updates |
Re-read shared state after an await instead of writing back a stale value. | — |
require_mirror_test |
Detect libraries under lib/ with no matching test file. | — |
use_class_prefix |
Require a name prefix for classes deriving from a configured type. | Yes |
use_class_suffix |
Require a name suffix for classes deriving from a configured type. | Yes |
use_closest_build_context |
Use the inner BuildContext from builder callbacks, not the outer one. | Yes |
use_dedicated_media_query_methods |
Use MediaQuery.sizeOf(context) instead of MediaQuery.of(context).size. | Yes |
use_existing_destructuring |
Add properties to an existing destructuring instead of accessing them directly. | Yes |
use_existing_variable |
Use an existing variable instead of repeating its initializer expression. | Yes |
use_gap |
Use Gap widget instead of SizedBox for spacing in multi-child widgets. | Yes |
use_ref_and_state_synchronously |
Check ref.mounted before using ref or state after an await. | Yes |
use_ref_read_synchronously |
Add a mounted guard before calling ref.read after an await. | Yes |
use_setstate_synchronously |
Guard setState after an await with a mounted check. | — |
use_sliver_prefix |
Name widgets that return slivers with a Sliver prefix. | Yes |
Detailed Examples #
avoid_single_child_in_multi_child_widgets #
Multi-child widgets like Column, Row, Wrap should not be used with only a single child.
❌ Bad:
Column(
children: [Text('Only child')],
)
✅ Good:
Text('Only child')
avoid_unnecessary_consumer_widgets #
ConsumerWidget should only be used when the WidgetRef is actually used.
❌ Bad:
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// ref is never used
return Text('Hello');
}
}
✅ Good:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Hello');
}
}
avoid_unnecessary_hook_widgets #
HookWidget should only be used when hooks are actually called.
❌ Bad:
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
// No hooks called
return Text('Hello');
}
}
✅ Good:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Hello');
}
}
prefer_align_over_container #
Use Align widget instead of Container when only alignment is set.
❌ Bad:
Container(
alignment: Alignment.topLeft,
child: Text('Hello'),
)
✅ Good:
Align(
alignment: Alignment.topLeft,
child: Text('Hello'),
)
prefer_any_or_every #
Use .any() instead of .where().isNotEmpty and .every() instead of .where().isEmpty.
❌ Bad:
final hasEven = numbers.where((n) => n.isEven).isNotEmpty;
final allPositive = numbers.where((n) => n < 0).isEmpty;
✅ Good:
final hasEven = numbers.any((n) => n.isEven);
final allPositive = numbers.every((n) => n >= 0);
prefer_center_over_align #
Use Center widget instead of Align when alignment is center.
❌ Bad:
Align(
alignment: Alignment.center,
child: Text('Hello'),
)
✅ Good:
Center(
child: Text('Hello'),
)
prefer_padding_over_container #
Use Padding widget instead of Container when only margin is set.
❌ Bad:
Container(
margin: EdgeInsets.all(16),
child: Text('Hello'),
)
✅ Good:
Padding(
padding: EdgeInsets.all(16),
child: Text('Hello'),
)
The banned family #
avoid_banned_imports, avoid_banned_exports, avoid_banned_types,
avoid_banned_names, avoid_banned_annotations and banned_usage all read
the same banned: entry shape and report nothing until configured — they
enforce your policy, not a built-in one. See many_lints.yaml.
rules:
avoid_banned_imports:
banned:
- deny: ['dart:io'] # exact match
in: ['lib/domain/**'] # optional glob scope; omit for everywhere
message: 'Keep the domain layer platform-independent.'
- deny_pattern: ['package:legacy_.*'] # anchored to the whole value
Each entry takes deny and/or deny_pattern, plus optional in and
message. deny matches exactly — banning async does not ban
dart:async — so patterns are always opt-in.
❌ Bad:
// in lib/domain/user_repository.dart
import 'dart:io';
✅ Good:
// in lib/domain/user_repository.dart
abstract class ConfigSource {
Future<String> read();
}
use_class_prefix #
Requires a configured name prefix for classes deriving from a configured type.
Reports nothing until configured — see many_lints.yaml.
rules:
use_class_prefix:
entries:
- type: Repository
prefix: Db
❌ Bad:
class UserRepository implements Repository {}
✅ Good:
class DbUserRepository implements Repository {}
use_class_suffix #
Requires a configured name suffix for classes deriving from a configured type.
Matches through extends, implements, with, or an indirect ancestor.
rules:
use_class_suffix:
entries:
- type: Bloc
package: bloc
suffix: Bloc
❌ Bad:
class CounterManager extends Bloc<CounterEvent, int> {}
✅ Good:
class CounterBloc extends Bloc<CounterEvent, int> {}
use_dedicated_media_query_methods #
Use dedicated MediaQuery methods to avoid unnecessary rebuilds.
❌ Bad:
final size = MediaQuery.of(context).size;
final padding = MediaQuery.of(context).padding;
final orientation = MediaQuery.of(context).orientation;
✅ Good:
final size = MediaQuery.sizeOf(context);
final padding = MediaQuery.paddingOf(context);
final orientation = MediaQuery.orientationOf(context);
use_gap #
Use Gap widget instead of SizedBox or Padding for spacing in multi-child widgets.
❌ Bad:
Column(
children: [
Text('First'),
SizedBox(height: 16),
Text('Second'),
],
)
✅ Good:
Column(
children: [
Text('First'),
Gap(16),
Text('Second'),
],
)
Suppressing Diagnostics #
To suppress a specific lint, use comments:
// ignore: many_lints/prefer_center_over_align
const example = Align(alignment: Alignment.center);
// ignore_for_file: many_lints/use_class_suffix
The many_lints/ prefix is required. Unlike SDK lints, a plugin diagnostic is only silenced when the rule name is prefixed with the plugin name, so a bare // ignore: prefer_center_over_align has no effect. The prefix is the key used under plugins: in analysis_options.yaml.
Suppressing by type is also possible via // ignore: type=lint (the type= form is required, and it silences every lint on that line, SDK ones included).
More Information #
See the individual example files in lib/ for complete, runnable code samples.