Skip to content

feat(bloc_lint): add prefer_multi_bloc_listener and prefer_multi_repository_provider - #4852

Open
TiwariAshuism wants to merge 1 commit into
felangel:masterfrom
TiwariAshuism:feat/prefer-multi-widget-lint-rules
Open

TiwariAshuism wants to merge 1 commit into
felangel:masterfrom
TiwariAshuism:feat/prefer-multi-widget-lint-rules

Conversation

@TiwariAshuism

Copy link
Copy Markdown

Status

READY

Breaking Changes

NO

Description

Adds two lint rules which warn when BlocListener or RepositoryProvider widgets are nested through the child argument, where a single MultiBlocListener / MultiRepositoryProvider is equivalent and easier to read.

// BAD
BlocListener<BlocA, BlocAState>(
  listener: (context, state) {},
  child: BlocListener<BlocB, BlocBState>(
    listener: (context, state) {},
    child: ChildA(),
  ),
);

// GOOD
MultiBlocListener(
  listeners: [
    BlocListener<BlocA, BlocAState>(listener: (context, state) {}),
    BlocListener<BlocB, BlocBState>(listener: (context, state) {}),
  ],
  child: ChildA(),
);

Implementation notes

Both rules are thin wrappers over a shared NestedWidgetListener (lib/src/nested_widget_listener.dart), parameterized by the widget name and its replacement.

  • Maintains a stack of the enclosing argument lists, recording for each whether it belongs to the watched widget and whether it sits in a child slot. A report fires only when the immediately enclosing invocation is the same widget, so a widget that merely has a matching ancestor higher up the tree is not flagged.
  • Only the outermost widget of a contiguous nested chain is reported, so a chain of three produces one diagnostic rather than two. Where the chain is broken by an unrelated callback, the innermost valid chain root is reported instead — both behaviours are covered by tests.
  • Resolves type arguments via endTypeArguments and named constructors via the preceding ., so BlocListener<A, B>(...), RepositoryProvider(...) and RepositoryProvider<A>.value(...) are all recognized.
  • Severity is info, matching the other prefer_* rules. These are readability rules — the two forms are equivalent at runtime, as the MultiBlocListener docs note.

Adding prefer_multi_bloc_provider (#4453) on top of this is a ~20 line change, should you want it — I left it out since that issue is assigned.

Verified locally against the CI gates: dart format, dart analyze --fatal-warnings lib test, full suite (172 tests, 21 new) and 100% coverage.

Closes #4454
Closes #4455

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

…sitory_provider

Warn when `BlocListener` or `RepositoryProvider` widgets are nested via
the `child` argument, where a single `MultiBlocListener` or
`MultiRepositoryProvider` would be equivalent and easier to read.

Both rules share a `NestedWidgetListener` which tracks the enclosing
argument lists so only the outermost widget of a nested chain is
reported, and a widget that merely has a matching ancestor further up
the tree is not.

Closes felangel#4454
Closes felangel#4455
@TiwariAshuism
TiwariAshuism requested a review from felangel as a code owner August 1, 2026 21:11

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(bloc_lint): prefer_multi_repository_provider feat(bloc_lint): prefer_multi_bloc_listener

1 participant