many_lints 0.9.0
many_lints: ^0.9.0 copied to clipboard
A comprehensive collection of custom lint rules, quick fixes, and code assists for Flutter and Dart projects.
Changelog #
0.9.0 - 2026-08-08 #
Added #
- Per-rule configuration, read from a
many_lints.yamlfile at the package root and falling back to a top-levelmany_lints:section inanalysis_options.yaml. The analyzer cannot carry per-rule configuration for a plugin —RuleConfigexposes only name, group and severity, and custom keys underplugins:are reported as unsupported options — so configuration lives in its own file. When both sources exist the dedicated file wins outright rather than merging, so a pattern always has one traceable origin. - An
excludekey on every one of the 133 rules, taking a list of glob patterns relative to the package root. Exclusion is per rule: silencing a noisy rule in generated or legacy code says nothing about the other 132, so a path can be skipped without weakening the rest of the suite. avoid_only_rethrowgains anignore_typed_catchesoption, which stops it reporting a catch clause that narrows the caught type (on FooException catch (e) { rethrow; }).
0.8.0 - 2026-08-07 #
Added #
avoid_duplicate_collection_elementsnow has a quick fix that removes the duplicate, keeping the first occurrence. It covers all three reported shapes: plain values, spreads andifelements.avoid_shrink_wrap_in_listsnow has a quick fix that removes theshrinkWrap: trueargument. The parameter defaults tofalse, so this is behaviour-preserving; a list that was shrink-wrapped because it nests inside another scrollable still needs the documentedCustomScrollViewrestructuring, which the fix deliberately does not attempt.- Quick fixes for the two widened rules that already had one now cover the newly reported shapes.
prefer_add_allcollapses a run of consecutiveaddcalls intoaddAll([...])(it previously only rewrote loops, so the new shape was reported with no fix available), andavoid_unnecessary_negationsrewrites!trueand!a == !b. test/plugin_fix_output_test.dartasserts the text a quick fix actually produces, by drivingedit.getFixesthrough thePluginServerharness and applying the returned edit.analyzer_testingstill has no fix test API, so fix output previously went unverified.
Fixed #
- 27 quick fixes never fired at all. They were registered and offered by name, but the IDE only ever showed the "Ignore …" suppression actions — selecting the fix did nothing. Each one type-tested the correction producer's
nodedirectly (if (node is! ConstructorName) return;,node.parent, …), which stopped matching after the analyzer 13 AST refactor:nodeCoveringresolves the diagnostic range to the deepest node, so an unnamedFoo(...)yieldsNamedTyperather thanConstructorName, and areportAtTokenon a class name yields a name-part wrapper rather than theClassDeclaration. Every affected fix now walks up withthisOrAncestorOfTypeinstead. Affected:avoid_incomplete_copy_with,avoid_incorrect_image_opacity,avoid_unnecessary_consumer_widgets,avoid_unnecessary_gesture_detector,avoid_unnecessary_overrides,avoid_unnecessary_overrides_in_state,avoid_unnecessary_setstate,avoid_unnecessary_stateful_widgets,avoid_wrapping_in_padding,list_all_equatable_fields,prefer_abstract_final_static_class,prefer_align_over_container,prefer_center_over_align,prefer_constrained_box_over_container,prefer_container,prefer_multi_bloc_provider,prefer_overriding_parent_equality,prefer_padding_over_container,prefer_returning_shorthands,prefer_sized_box_square,prefer_switch_expression,prefer_text_rich,prefer_transform_over_container,prefer_type_over_var,use_closest_build_context,use_gap,use_sliver_prefix. - The three suffix fixes (
use_bloc_suffix,use_cubit_suffix,use_notifier_suffix) had the same problem, and additionally renamed only the class — leavingclass FooBloc { Foo(); }, which does not compile. They now rename any same-named constructor along with the class. avoid_generics_shadowingrenamed the type parameter's declaration but left its usages behind (void process<T>(Config c) {}— not compilable). It located the declaring scope with a fixedparent.parenthop, which stopped reaching class and top-level-function declarations once analyzer 13 added intermediate nodes; it now walks up.avoid_incomplete_copy_withemitteddynamicfor any parameter declared as a field formal (required this.name), since those carry no type annotation. It now falls back to the resolved element type, producingString? surname.prefer_switch_expressionhandled only pre-Dart-3SwitchCasemembers. Dart 3 parsescase Status.active:as aSwitchPatternCase, so the fix bailed on essentially every modern switch it was offered for.prefer_expect_lateremitted two edits starting at the same offset (replacingexpectand insertingawaitbefore it). Overlapping edits raiseConflictingEditException, whichFixProcessorcatches and logs — silently discarding the entire fix. It now emits a single edit.use_closest_build_contextignored untyped closure parameters ((_) { … }), because it read only the type annotation while the rule itself falls back to the resolved element type. The two now agree, so the fix can act on every case the rule reports.avoid_commented_out_codeno longer merges unrelated comments into one block. Comments were grouped by character distance (any gap under 150 characters), which reached across blank lines, closing braces, and whole class boundaries — the check for a blank line compared the same distance as the grouping condition, so it could never fire. A block of commented-out code followed by ordinary prose comments elsewhere in the file merged into a single group whose code-line ratio fell below the threshold, silencing the diagnostic for the entire file. Comments are now grouped only when they sit on directly consecutive lines with nothing but whitespace between them, and a comment trailing code (foo(); // note) starts its own group. This makes the rule report in files where it previously found nothing.
Changed #
Four rules were widened so that a rule name means the same thing here as it does in DCM. Each now covers everything it did before plus the shapes DCM reports, so existing projects will see new diagnostics on code that previously passed.
prefer_add_allnow also reports consecutiveaddcalls on the same collection (values.add(a); values.add(b);), not only an add-onlyfor-inloop. A run is broken by any other statement, and the receiver must be a stable expression of a collection type, soaddon an unrelated class is left alone.avoid_duplicate_collection_elementsnow reports repeated spreads ([...items, ...items]) and repeatedifelements, and no longer stops analysing a literal at the first spread orifelement —[1, ...base, 1]was previously missed. Spreads inside set and map literals are checked too; plain values there remain out of scope, since the analyzer reports those natively.avoid_unnecessary_negationsnow reports a negated boolean literal (!true) and negations on both sides of a comparison (!a == !b,!a != !b). A single negation in a comparison is still left alone, since removing it would change the result.prefer_switch_with_enumsnow counts comparisons joined by||toward its threshold, and reports a membership test over a literal collection of enum constants ({E.a, E.b, E.c}.contains(value)). A named collection is not reported — it is a reusable set rather than an inlined branch.
avoid_misused_hooks and avoid_shrink_wrap_in_lists were reviewed against DCM and left unchanged: hooks called outside a hook context are already covered by avoid_hooks_outside_build, and avoid_shrink_wrap_in_lists already reports every shrinkWrap: true rather than only nested ones.
Documentation #
- Example files and rule pages for the four widened rules now show the added shapes.
- Rewrote the code examples for 17 rules that had drifted into reproducing DCM's documentation verbatim (shared class names, method names, and literal values). Behaviour is unchanged.
use_notifier_suffixno longer claims to coverAsyncNotifier; it checksNotifieronly, and the two are unrelated hierarchies in Riverpod.prefer_shorthands_with_constructorsdocuments that it does not resolve the destination parameter's declared type, so adynamicparameter is still reported.- Fixed a type error in the
prefer_use_prefixexample (useStatereturnsValueNotifier<T>, notT) and an undeclared class in theavoid_passing_bloc_to_blocexample. - Moved
prefer_compute_over_isolate_runout of the "Testing Rules" category; it is about web platform compatibility.
0.7.1 - 2026-08-03 #
Fixed #
avoid_unnecessary_stateful_widgetsno longer fires when a mixin applied to theStatecarries the state. A mixinon State<T>can hold the mutable fields, the lifecycle overrides or thesetStatecalls on behalf of the class that applies it, which left theStatebody looking empty while the widget was genuinely stateful. Computed getters on such a mixin still do not count as state.avoid_unnecessary_consumer_widgetsnow reportsConsumerStatefulWidget. The rule matched it but then looked for abuildwith arefparameter on the widget itself, which aConsumerStatefulWidgetnever has — itsrefis a getter on the companionConsumerState— so that half of the rule never reported anything. The widget is now correlated with its state class, and anyrefuse in that class counts, not only one insidebuild.avoid_unnecessary_consumer_widgetsno longer fires when a mixin uses therefon the class's behalf. A mixinon ConsumerState<T>is a normal way to share provider access, and it left the state body looking ref-free while the widget genuinely needed the container. A mixin carrying norefuse still does not suppress the diagnostic.
Documentation #
- Documented that suppression comments for plugin lints require the plugin-name prefix (
// ignore: many_lints/<rule>). A bare// ignore: <rule>has no effect, which is easy to mistake for the rule ignoring suppression altogether. Type-based suppression needs thetype=form (// ignore: type=lint).
0.7.0 - 2026-07-15 #
Added #
prefer_private_named_parametersrule with quick fix — suggests Dart 3.12 private named parameters (this._field) over_field = fieldinitializer-list boilerplate; only active in libraries with language version 3.12+prefer_theme_mode_gettersrule with quick fix — suggests theThemeMode.isDark/isLight/isSystemgetters (Flutter 3.44+) over==/!=comparisons againstThemeModeconstants; only active when the getters exist in the project's Flutter version
0.6.0 - 2026-07-15 #
Changed #
- Bump
analyzerconstraint to^14.1.0(support for the latest Dart/Flutter SDKs) - Bump
analyzer_pluginconstraint to^0.14.14 - Bump
analysis_server_pluginconstraint to^0.3.20 - Bump
analyzer_testingconstraint to^0.3.4
0.5.0 - 2026-07-15 #
Changed #
- Bump
analyzerconstraint to^13.3.0(support for the latest Dart/Flutter SDKs) - Bump
analyzer_pluginconstraint to^0.14.12 - Bump
analysis_server_pluginconstraint to^0.3.18 - Bump
analyzer_testingconstraint to^0.3.2 - Migrate all rules and quick fixes to the analyzer 13 AST API (
NamedArgument,Argument,RegularFormalParameter)
0.4.4 - 2026-06-18 #
Fixed #
prefer_shorthands_with_enumsnow infers enum shorthand context correctly for named arguments.
0.4.3 - 2026-05-08 #
Fixed #
- Diagnostics configuration now works correctly when
many_lintsis loaded through the legacy plugin server constructor.
0.4.2 - 2026-05-08 #
Fixed #
- Respect
diagnosticsconfiguration so individualmany_lintsrules can be disabled fromanalysis_options.yaml.
0.4.1 - 2026-05-07 #
Changed #
- Bump
analyzerconstraint to^12.1.0 - Bump
analyzer_pluginconstraint to^0.14.8 - Bump
analysis_server_pluginconstraint to^0.3.14 - Bump
analyzer_testingconstraint to^0.2.5 - Bump
testconstraint to^1.31.1 - Drop the
analyzerdependency_overridesblock (no longer needed oncetest 1.31.1lifted its analyzer upper bound)
0.4.0 - 2026-02-20 #
Added #
Dart & Code Quality Rules
avoid_constant_conditionsrule to warn when both sides of a comparison are constantsavoid_constant_switchesrule to warn when a switch expression is a constantavoid_contradictory_expressionsrule to detect contradictory comparisons in&&chainsavoid_duplicate_cascadesrule to detect duplicate cascade sections with quick fixavoid_generics_shadowingrule to warn when a generic type parameter shadows a top-level declaration with quick fixavoid_incomplete_copy_withrule to detectcopyWithmethods missing constructor parameters with quick fixavoid_map_keys_containsrule to prefercontainsKey()over.keys.contains()with quick fixavoid_misused_test_matchersrule to detect incompatible matcher usageavoid_only_rethrowrule to flag catch clauses that only rethrow with quick fixavoid_single_field_destructuringrule to avoid single-field destructuring with quick fixavoid_throw_in_catch_blockrule to avoidthrowinside catch blocks with quick fixavoid_unassigned_stream_subscriptionsrule to detect unassigned stream subscriptionslist_all_equatable_fieldsrule to detect Equatable subclasses with missing fields inpropswith quick fixprefer_class_destructuringrule to suggest class destructuring for repeated property accesses with quick fixprefer_containsrule to prefer.contains()over.indexOf()compared to-1with quick fixprefer_enums_by_namerule to prefer.byName()over.firstWhere()with quick fixprefer_equatable_mixinrule to preferEquatableMixinover extendingEquatablewith quick fixprefer_expect_laterrule to preferexpectLaterwhen testing Futures with quick fixprefer_overriding_parent_equalityrule to detect missing==/hashCodeoverrides with quick fixprefer_return_awaitrule to detect missingawaitintry-catchwith quick fixprefer_simpler_patterns_null_checkrule to prefer simpler null-check patterns in if-case expressions with quick fixprefer_single_widget_per_filerule to enforce one public widget per fileprefer_test_matchersrule to prefer matchers over literals inexpect()prefer_wildcard_patternrule to prefer_overObject()with quick fixproper_super_callsrule to enforce correct super call placement with quick fixuse_closest_build_contextrule to use the closest availableBuildContextwith quick fixuse_existing_destructuringrule to use existing destructuring instead of direct access with quick fixuse_existing_variablerule to detect duplicate initializer expressions with quick fix
Flutter Widget Rules
always_remove_listenerrule to detect listeners not removed indispose()with quick fixavoid_border_allrule to preferBorder.fromBorderSideoverBorder.allwith quick fixavoid_conditional_hooksrule to detect hooks called inside conditionals or loopsavoid_expanded_as_spacerrule to preferSpaceroverExpandedwith empty child with quick fixavoid_flexible_outside_flexrule to flagFlexible/ExpandedoutsideRow/Column/Flexavoid_incorrect_image_opacityrule to useImage'sopacityparameter with quick fixavoid_mounted_in_setstaterule to detectmountedcheck insidesetStateavoid_returning_widgetsrule to avoid returning widgets from functions/methodsavoid_shrink_wrap_in_listsrule to avoidshrinkWrapinListViewavoid_unnecessary_gesture_detectorrule to flagGestureDetectorwith no handlers with quick fixavoid_unnecessary_overridesrule to detect overrides that only callsuperwith quick fixavoid_unnecessary_overrides_in_staterule to detect State overrides that only callsuperwith quick fixavoid_unnecessary_setstaterule to detect unnecessarysetStatecalls with quick fixavoid_unnecessary_stateful_widgetsrule to detectStatefulWidgetwith no mutable state with quick fixavoid_wrapping_in_paddingrule to avoid wrapping inPaddingwhen widget has padding support with quick fixdispose_fieldsrule to detect undisposed fields with quick fixprefer_async_callbackrule to preferAsyncCallbackoverFuture<void> Function()with quick fixprefer_compute_over_isolate_runrule for web platform compatibility with quick fixprefer_const_border_radiusrule to preferBorderRadius.all(Radius.circular())with quick fixprefer_constrained_box_over_containerrule to preferConstrainedBoxoverContainerwith quick fixprefer_containerrule to merge nested widgets into a singleContainerwith quick fixprefer_correct_edge_insets_constructorrule to use simplerEdgeInsetsconstructors with quick fixprefer_for_loop_in_childrenrule to prefer for-loops over functional list building with quick fixprefer_single_setstaterule to merge multiplesetStatecalls with quick fixprefer_sized_box_squarerule to preferSizedBox.squarewith quick fixprefer_spacingrule to prefer thespacingargument overSizedBoxprefer_text_richrule to preferText.richoverRichTextwith quick fixprefer_transform_over_containerrule to preferTransformoverContainerwith quick fixprefer_use_callbackrule to preferuseCallbackover inline closures with quick fixprefer_use_prefixrule to preferuseprefix for custom hook functions with quick fixprefer_void_callbackrule to preferVoidCallbackovervoid Function()with quick fixuse_sliver_prefixrule to enforceSliverprefix for sliver-returning widgets with quick fix
BLoC Rules
avoid_bloc_public_methodsrule to avoid public members in Bloc classesavoid_passing_bloc_to_blocrule to avoid passing Bloc/Cubit to another Bloc/Cubitavoid_passing_build_context_to_blocsrule to avoid passingBuildContextto Bloc/Cubitprefer_bloc_extensionsrule to prefercontext.read/context.watchwith quick fixprefer_immutable_bloc_staterule to annotate Bloc state with@immutablewith quick fixprefer_multi_bloc_providerrule to preferMultiBlocProviderwith quick fix
Riverpod Rules
avoid_notifier_constructorsrule to avoid constructors with logic in Notifier classes with quick fixavoid_public_notifier_propertiesrule to avoid public non-overridden properties in Notifier classesavoid_ref_inside_state_disposerule to avoid accessingrefinsidedispose()avoid_ref_read_inside_buildrule to avoidref.readinsidebuildwith quick fixavoid_state_constructorsrule to avoid constructors with logic in State classes with quick fixdispose_provided_instancesrule to detect instances not disposed viaref.onDispose()with quick fixuse_ref_and_state_synchronouslyrule to detect async gaps beforeref/stateaccess with quick fixuse_ref_read_synchronouslyrule to detectref.readstored across async gaps with quick fix
Changed #
- Extracted shared utility
lib/src/constant_expression.dartfor constant expression checking - Updated README and example README to document all 100 rules and 78 quick fixes
0.3.0 - 2026-02-14 #
Added #
prefer_shorthands_with_enumsrule to detect enum values replaceable with shorthand constructorsprefer_shorthands_with_constructorsrule to detect constructors replaceable with shorthand syntaxprefer_shorthands_with_static_fieldsrule to detect static fields replaceable with shorthand syntaxprefer_returning_shorthandsrule to detect return statements replaceable with shorthand syntaxprefer_switch_expressionrule to suggest using switch expressions over switch statementsprefer_explicit_function_typerule to prefer explicit function types overFunctionprefer_type_over_varrule to prefer explicit type annotations overvarprefer_abstract_final_static_classrule to flag utility classes that should be abstract finalprefer_iterable_ofrule to preferIterable.ofoverIterable.fromfor same-type conversionsavoid_accessing_collections_by_constant_indexrule to flag hardcoded index access on collectionsavoid_cascade_after_if_nullrule to detect cascades after if-null operatorsavoid_collection_equality_checksrule to flag equality checks on collectionsavoid_collection_methods_with_unrelated_typesrule to flag collection method calls with unrelated typesavoid_commented_out_coderule to detect commented-out code blocks
Changed #
- Extracted shared utilities, renamed helpers, and refactored suffix rules
0.2.1 - 2026-02-05 #
0.2.0 - 2026-02-05 #
Added #
use_gaprule to preferGapwidget overSizedBoxorPaddingfor spacing- Quick fixes for suffix rules (
use_bloc_suffix,use_cubit_suffix,use_notifier_suffix) - Quick fix for
avoid_unnecessary_consumer_widgetsrule - Example project demonstrating all lint rules
- Dartdoc comments to public APIs
Changed #
- Renamed test methods to snake_case for consistency
- Applied recommended lints from
lintspackage
0.1.2 - 2026-02-04 #
Fixed #
- Add
lib/main.dartre-export for properanalysis_server_plugindiscovery - Replace deprecated analyzer API usages with new equivalents
0.1.0 - 2026-02-04 #
Added #
avoid_single_child_in_multi_child_widgets- detect single-child usage in multi-child widgetsavoid_unnecessary_consumer_widgets- flag unnecessary Riverpod consumer widgetsavoid_unnecessary_hook_widgets- flag unnecessary hook widgets with quick fixprefer_align_over_container- preferAlignoverContainerfor alignment onlyprefer_any_or_every- preferany/everyover manual iteration with quick fixprefer_center_over_align- preferCenteroverAlignfor centering with quick fixprefer_padding_over_container- preferPaddingoverContainerfor padding only with quick fixuse_bloc_suffix- enforceBlocsuffix on bloc classesuse_cubit_suffix- enforceCubitsuffix on cubit classesuse_dedicated_media_query_methods- prefer dedicatedMediaQuerymethods with quick fixuse_notifier_suffix- enforceNotifiersuffix on notifier classesconvert_iterable_map_to_collection_forassist