Configuration
Installation
Section titled “Installation”Add many_lints to the top-level plugins section in your analysis_options.yaml file (NOT under analyzer:):
plugins: many_lints: ^1.1.0The analysis server will automatically download and resolve the plugin from pub.dev. There is no need to add it to your pubspec.yaml.
Requires Dart 3.11+ (Flutter 3.41+)
Extended syntax
Section titled “Extended syntax”You can use the extended syntax to pin a version:
plugins: many_lints: version: ^1.1.0Choosing rules
Section titled “Choosing rules”Every rule is off by default, but a preset is not required. You can enable only the rules you choose, start from a preset, or start from a preset and override individual rules. Installing the plugin alone therefore never floods an existing codebase with warnings.
Selecting individual rules
Section titled “Selecting individual rules”Use this mode when you want a small, explicit rule set:
many_lints: rules: avoid_equal_expressions: true avoid_only_rethrow: enabled: true exclude: test/**# many_lints.yaml — next to pubspec.yamlrules: avoid_equal_expressions: true avoid_only_rethrow: enabled: true exclude: test/**The boolean and enabled: forms are equivalent. Adding include, exclude, message,
or a rule-specific option also enables that rule unless you explicitly set
enabled: false.
Starting from a preset
Section titled “Starting from a preset”Presets are optional shortcuts for enabling a maintained group of rules. Select one with
the preset: key, in either of the two config locations described below:
many_lints: preset: recommended# many_lints.yaml — next to pubspec.yamlpreset: recommendedThe presets
Section titled “The presets”The dedicated Presets guide explains the philosophy of every tier and lists the exact rules each one adds.
| Preset | Rules | What it contains |
|---|---|---|
none |
0 | Nothing. The default, and the explicit way to opt out. |
core |
35 | Near-certain bugs only. |
recommended |
97 | core plus likely defects and concrete runtime risks. |
opinionated |
184 | recommended plus this package’s own style preferences. |
pedantic |
241 | opinionated plus strict naming, structure, complexity and ordering. |
Each preset builds on the one above it, the same way package:lints/recommended.yaml
includes core.yaml — moving up a tier only ever adds rules.
core flags what is almost certainly a bug: a condition that is always true, a cast
that can never succeed, an undisposed controller, an emit(state) that is silently
dropped. Near-zero false positives and no stylistic judgement, so it is safe to adopt in
a large legacy codebase.
recommended is the tier most projects want. It adds widely-agreed practice — using
containsKey over keys.contains, passing an existing future to a FutureBuilder,
keeping enum switches exhaustive. It deliberately excludes anything that imposes an
architecture, a naming scheme, or a contested style choice.
opinionated adds the rules that enforce a particular taste (widget-swapping rules,
shorthand preferences, prefer_type_over_var). Where reasonable codebases disagree, this
tier takes a side — so expect to switch a few rules back off rather than to agree with all
of it.
pedantic is the deliberately uncompromising tier. It adds one declaration per file,
file/type-name matching, constructor-first member ordering, alphabetical ordering for
named parameters, arguments, enum constants, map keys, record fields and pattern fields,
complexity and size budgets, explicit callback parameter names, and stricter naming rules.
It also removes the usual map[key]! exemption from avoid_non_null_assertion.
The plugin cannot enable SDK lints, so pair this preset with analyzer rules such as
always_specify_types, directives_ordering, sort_constructors_first,
sort_unnamed_constructors_first and sort_child_properties_last if you want the complete
Flutter-strict style rather than only the custom rules supplied by this package.
Two other groups sit outside every preset. Rules that do nothing until you configure them —
avoid_banned_imports, use_class_suffix and the rest of the banned_* family — because
an unconfigured banned-list has nothing to report. And rules that assume a package you may
not depend on, such as use_gap (the gap package) and the equatable rules.
Adjusting a preset
Section titled “Adjusting a preset”enabled: overrides the preset for one rule, in either direction, so you never have to
restate a preset’s contents to tweak it:
many_lints: preset: recommended rules: # Add a rule the preset leaves out. use_class_suffix: enabled: true entries: - type: Bloc suffix: Bloc # Drop one the preset includes. avoid_only_rethrow: enabled: false# many_lints.yaml — next to pubspec.yamlpreset: recommendedrules: # Add a rule the preset leaves out. use_class_suffix: enabled: true entries: - type: Bloc suffix: Bloc # Drop one the preset includes. avoid_only_rethrow: enabled: falseWhen a rule needs nothing but on-or-off, the terse spelling works too:
many_lints: rules: prefer_type_over_var: true avoid_only_rethrow: false# many_lints.yaml — next to pubspec.yamlrules: prefer_type_over_var: true avoid_only_rethrow: falseSeverity
Section titled “Severity”preset: and enabled: decide whether a rule runs. To change how loudly it reports,
use the analyzer’s own diagnostics: key:
plugins: many_lints: version: ^1.1.0 diagnostics: avoid_equal_expressions: error # error | warning | infoExcluding paths per rule
Section titled “Excluding paths per rule”A preset turns a rule on everywhere. To keep a rule on but silence it for
certain paths, write a rules: block — in either of these two places, whichever
you prefer.
The recommended location is a top-level many_lints: key in analysis_options.yaml — a
sibling of plugins:, not nested inside it. A standalone many_lints.yaml next to
pubspec.yaml is fully equivalent.
plugins: many_lints: ^1.1.0
many_lints: rules: avoid_only_rethrow: exclude: - test/** - "**/*.g.dart"# many_lints.yaml — next to pubspec.yamlrules: avoid_only_rethrow: exclude: - test/** - "**/*.g.dart"Which to pick
Section titled “Which to pick”Use analysis_options.yaml for the normal single-file setup. Choose standalone
many_lints.yaml only when you deliberately want plugin configuration separated. If you
create both, many_lints.yaml wins outright; they are not merged.
What exclude accepts
Section titled “What exclude accepts”Every rule supports exclude. 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.
Patterns are globs matched against the path relative to the package root, using the same
glob semantics as the analyzer’s own analyzer: exclude:. A plain path is a valid
pattern too, and the list can hold as many entries as you need:
many_lints: rules: avoid_only_rethrow: exclude: - lib/legacy/parser.dart # one specific file - lib/generated/** # a whole directory tree - "**/*.g.dart" # every generated file prefer_type_over_var: exclude: - test/** # a different rule, its own list# many_lints.yaml — next to pubspec.yamlrules: avoid_only_rethrow: exclude: - lib/legacy/parser.dart - lib/generated/** - "**/*.g.dart" prefer_type_over_var: exclude: - test/**Limiting a rule to certain paths
Section titled “Limiting a rule to certain paths”include is the inverse of exclude: the rule runs only where it matches.
many_lints: rules: avoid_banned_imports: include: - lib/domain/** # architectural rules are most useful scoped# many_lints.yaml — next to pubspec.yamlrules: avoid_banned_imports: include: - lib/domain/**Like exclude, it takes globs relative to the package root, and a bare string works
where you only need one pattern (include: lib/domain/**).
Omitting include, or leaving it empty, means “everywhere” — the default. When a file
matches both lists exclude wins, so the two only ever narrow further and you never
have to reason about which was written first.
Adding a note to a rule’s message
Section titled “Adding a note to a rule’s message”message appends a sentence to every diagnostic a rule reports, which turns a generic
lint into your team’s house style:
many_lints: rules: avoid_border_all: message: Use AppBorders from our design system.# many_lints.yaml — next to pubspec.yamlrules: avoid_border_all: message: Use AppBorders from our design system.warning • Prefer Border.fromBorderSide over Border.all. Use AppBorders from our design system. • many_lints/avoid_border_allThe rule’s own text is kept and the diagnostic code is unchanged, so // ignore:
comments, severity overrides and quick fixes all keep working.
Both include and message work on every rule, exactly like exclude.
Per-rule options
Section titled “Per-rule options”Beyond exclude, include and message, 120 rules accept options that change what
they report. Those rules carry a Configurable
badge on their page, and every option is documented there with its type and default.
Options go in the same rules: block as exclude, in whichever of the two files you chose
above:
many_lints: rules: prefer_container: exclude: - test/** # works on every rule min_sequence: 4 # an option, specific to this rule# many_lints.yaml — next to pubspec.yamlrules: prefer_container: exclude: - test/** min_sequence: 4Every option defaults to the rule’s previous behaviour, so adding this package’s options never changes results until you set one.
| Rule | Options |
|---|---|
always_remove_listener |
state_base_classes |
avoid_ad_hoc_left_type |
error_types, allow_subtypes |
avoid_banned_annotations |
banned |
avoid_banned_exports |
banned |
avoid_banned_imports |
banned |
avoid_banned_names |
banned |
avoid_banned_types |
banned |
avoid_empty_catch |
allow_with_comment |
avoid_exit_outside_entrypoint |
allow_in, additional_allow_in |
avoid_skipped_tests |
allow_reason |
avoid_throw_in_fp_callback |
ignore_unimplemented, methods, additional_methods |
avoid_collection_methods_with_unrelated_types |
strict |
avoid_commented_out_code |
min_lines |
avoid_default_tostring |
report_enums |
avoid_duplicate_bloc_event_handlers |
additional_methods |
avoid_duplicate_collection_elements |
ignore_literals |
avoid_non_null_assertion |
ignore_checked_fields, ignore_map_indexes |
avoid_empty_setstate |
state_base_classes |
avoid_get_or_else_swallowing_failure |
ignore_tests |
avoid_hooks_outside_build |
additional_methods |
avoid_inherited_widget_in_initstate |
state_base_classes |
avoid_late_context |
state_base_classes |
avoid_missing_completer_stack_trace |
require_inside_catch |
avoid_misused_hooks |
ignored_names, ignored_widgets |
avoid_mounted_in_setstate |
state_base_classes |
avoid_not_encodable_in_to_json |
allowed_types |
avoid_only_rethrow |
ignore_typed_catches |
avoid_passing_async_when_sync_expected |
ignore_widget_callbacks, ignored_parameters |
avoid_recursive_widget_calls |
state_base_classes |
avoid_removed_fpdart_api |
additional_removed |
avoid_returning_widgets |
ignored_names, ignored_annotations, additional_ignored_annotations, allow_nullable |
avoid_state_constructors |
state_base_classes |
avoid_todo_comments |
markers, additional_markers, require_reference, reference_pattern |
avoid_unassigned_stream_subscriptions |
ignored_instances |
avoid_unnecessary_setstate |
state_base_classes |
avoid_unnecessary_stateful_widgets |
state_base_classes |
avoid_unnecessary_option |
ignore_public_api |
avoid_unrelated_type_casts |
report_is_checks |
avoid_unremovable_callbacks_in_listeners |
additional_methods |
avoid_unrun_task |
additional_types, ignore_cascades |
avoid_complex_conditions |
max_operands |
avoid_long_functions |
max_lines |
avoid_long_parameter_list |
max_positional, max_named |
avoid_nested_conditional_expressions |
max_depth |
banned_usage |
banned |
check_for_equals_in_render_object_setters |
additional_methods |
check_is_not_closed_after_async_gap |
additional_methods |
dispose_fields |
cleanup_methods, additional_cleanup_methods, state_base_classes |
dispose_provided_instances |
cleanup_methods, additional_cleanup_methods |
emit_new_bloc_state_instances |
additional_methods |
prefer_chaining_over_intermediate_run |
min_sequence |
prefer_do_notation |
max_flat_map_depth, max_flatmap_depth (deprecated alias) |
prefer_class_destructuring |
min_occurrences, ignored_types |
prefer_container |
min_sequence |
prefer_from_predicate |
max_condition_complexity |
prefer_immutable_state |
name_pattern |
member_ordering |
order |
match_lib_folder_structure |
root |
prefer_match_file_name |
ignored_suffixes, entrypoints, additional_entrypoints |
prefer_correct_test_file_name |
directories, additional_directories |
format_test_name |
pattern, check_groups |
format_comment |
check_regular_comments |
no_magic_number |
allowed, additional_allowed, ignored_invocations, additional_ignored_invocations, ignore_tests |
no_magic_string |
min_occurrences, min_length, ignored_invocations, additional_ignored_invocations, ignore_tests |
prefer_extracting_callbacks |
max_statements, report_functions, ignored_parameters, additional_ignored_parameters |
prefer_named_parameters |
max_positional, ignored_names, additional_ignored_names, ignore_private_constructors |
prefer_explicit_parameter_names |
min_parameters |
prefer_explicit_type_arguments |
methods, additional_methods |
avoid_accessing_other_classes_private_members |
ignored_members, additional_ignored_members |
prefer_correct_type_name |
min_length, max_length, ignored_names |
prefer_moving_to_variable |
max_extra_occurrences, allowed_duplicated_chains (deprecated alias), min_chain_length, ignored_invocations, ignored_targets |
prefer_private_named_parameters |
only_same_name |
prefer_safe_collection_access |
report_outside_pipelines, accessors, additional_accessors |
prefer_shorthands_with_constructors |
classes, additional_classes |
prefer_single_declaration_per_file |
kinds, types, ignore_private, ignore_visible_for_testing, groups |
prefer_single_setstate |
state_base_classes |
prefer_single_widget_per_file |
ignore_private_widgets, ignore_visible_for_testing |
prefer_spacing |
min_children |
prefer_string_parse_extensions |
additional_parsers |
prefer_switch_expression |
allow_fallthrough_cases |
prefer_task_either_over_try_catch |
class_suffixes, additional_class_suffixes, ignore_private |
prefer_switch_with_enums |
ignore_contains |
prefer_typed_exceptions |
allow, additional_allow |
prefer_unit_over_void |
ignore_overrides |
proper_super_calls |
state_base_classes |
require_atomic_async_updates |
include_local_variables |
require_mirror_test |
test_dir, suffix, fallback_anywhere |
use_class_prefix |
entries, ignore_private |
use_class_suffix |
entries, ignore_private |
use_gap |
min_children |
use_sliver_prefix |
state_base_classes |
use_setstate_synchronously |
state_base_classes |
match_class_name_pattern |
pattern |
prefer_correct_error_name |
exception_suffix, error_suffix, allow_suffixes |
prefer_correct_handler_name |
prefixes, additional_prefixes, require_private |
prefer_correct_identifier_length |
min_length, max_length, allow_names, additional_allow_names |
prefer_correct_setter_parameter_name |
parameter_name, allow_names |
prefer_prefixed_global_constants |
prefix |
arguments_ordering |
order, min_arguments |
enum_constants_ordering |
order |
initializers_ordering |
order |
map_keys_ordering |
order, min_entries |
parameters_ordering |
order, group_required, min_parameters |
pattern_fields_ordering |
order |
record_fields_ordering |
order |
avoid_deep_nesting |
max_depth |
avoid_high_cyclomatic_complexity |
max_complexity, count_exhaustive_switches |
avoid_long_files |
max_lines, count_comments |
avoid_too_many_methods |
max_methods, count_accessors |
max_imports |
max_imports, count_exports |
max_statements |
max_statements |
avoid_negated_conditions |
report_not_equal |
prefer_early_return |
min_statements |
avoid_inconsistent_digit_separators |
group_size, hex_group_size |
double_literal_format |
leading_zero, trailing_zero |
avoid_future_of_either |
ignore_private |
avoid_future_of_option |
ignore_private |
prefer_typedefs_for_callbacks |
min_parameters |
avoid_deep_widget_nesting |
max_depth |
avoid_too_many_widgets_per_build |
max_widgets |
state_base_classes is accepted by every rule that only applies inside a
StatefulWidget’s State. Name a base class that does not extend Flutter’s
State and those rules will treat it as one; an intermediate BaseState<T> that
already extends State is recognised without any configuration.
Each option is documented with its type and default in the Options section of the rule’s own page.
Naming conventions
Section titled “Naming conventions”Option names follow a fixed vocabulary, so the same idea always reads the same way:
| Pattern | Meaning |
|---|---|
max_<unit> / min_<unit> |
A numeric bound; the unit is always named |
ignore_<singular> |
A toggle that skips a whole class of thing (ignore_private) |
ignored_<plural> |
A list of specific things to skip |
<plural> |
Replaces a built-in list (cleanup_methods) |
additional_<plural> |
Extends a built-in list (additional_cleanup_methods) |
name_pattern |
A regular expression matched against a name |
entries |
A list of maps, for rules driven entirely by what you configure |
Prefer additional_* over restating a built-in list: a copied-out default silently
misses any entry added in a later release.
Invalid values never break analysis
Section titled “Invalid values never break analysis”A misspelled key is ignored, and a wrong-typed value falls back to the default rather than throwing. This is deliberate — a plugin cannot report problems against a YAML file, so a bad option cannot be surfaced as a diagnostic. If an option seems to have no effect, check its spelling and type against the rule’s page.
Suppressing diagnostics
Section titled “Suppressing diagnostics”To suppress a specific lint, use comments:
// ignore: many_lints/prefer_center_over_alignconst Align(alignment: Alignment.center);
// ignore_for_file: many_lints/use_class_suffixRestarting the analysis server
Section titled “Restarting the analysis server”VS Code: Open the command palette (Cmd+Shift+P / Ctrl+Shift+P) and run Dart: Restart Analysis Server.
Android Studio / IntelliJ: Go to File → Invalidate Caches / Restart, or use the Dart Analysis panel to restart.