Skip to content

feat(bloc_lint): add avoid_mutable_events - #4853

Open
TiwariAshuism wants to merge 2 commits into
felangel:masterfrom
TiwariAshuism:feat/avoid-mutable-events
Open

feat(bloc_lint): add avoid_mutable_events#4853
TiwariAshuism wants to merge 2 commits into
felangel:masterfrom
TiwariAshuism:feat/avoid-mutable-events

Conversation

@TiwariAshuism

Copy link
Copy Markdown

Status

READY

Breaking Changes

NO

Description

Adds the avoid_mutable_events lint rule, which warns when a bloc event exposes mutable state through a non-final instance field or a setter.

sealed class CounterEvent {}

final class CounterIncrementPressed extends CounterEvent {
  CounterIncrementPressed(this.amount);

  int amount; // LINT
}

Rationale

Events are not handled the moment they are added — they are queued and processed asynchronously, and an EventTransformer such as debounce or throttle can delay them further. Mutating an event after it has been added means the handler observes different data than the caller intended, and the behavior depends on timing. Mutable fields also break the value equality blocs and tests rely on when comparing events.

Implementation notes

  • A class is treated as an event when its own name ends in Event (the sealed base) or its superclass name ends in Event (the subclasses), matching how the existing rules identify blocs and cubits via endsWith('Bloc') / endsWith('Cubit').
  • Reports non-final instance fields (including var and bare late) and setters. Static fields, const fields, late final fields and getters are left alone.
  • State is reset on endClassDeclaration, so a plain class or top-level variable following an event class is not affected — covered by tests.

Scoped to extends and the class name, deliberately matching the other rules. implements is not considered; happy to add it if you'd prefer.

The sibling rule avoid_mutable_states (#4451) would be close to a copy of this with a different suffix — 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 (165 tests, 14 new) and 100% coverage.

Closes #4452

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

Warn when a bloc event exposes mutable state via a non-final instance
field or a setter.

Events are queued and processed asynchronously, and an EventTransformer
can delay them further, so mutating an event after it has been added
makes the data seen by the handler depend on timing. Mutable fields also
break the value equality blocs and tests rely on when comparing events.

A class is treated as an event when its own name or the name of its
superclass ends in `Event`, matching how the existing rules identify
blocs and cubits. Static and `const` fields, `late final` fields and
getters are left alone.

Closes felangel#4452
@TiwariAshuism
TiwariAshuism requested a review from felangel as a code owner August 1, 2026 21:18
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): avoid_mutable_events

1 participant