mz_lints 0.0.1 copy "mz_lints: ^0.0.1" to clipboard
mz_lints: ^0.0.1 copied to clipboard

Custom Dart lint rules for Flutter apps. Includes rules for proper disposal of ChangeNotifiers, listener cleanup, and Controller lookup patterns.

mz_lints #

pub package CI codecov License: MIT

Custom Dart lint rules for Flutter applications. Helps catch common mistakes with ChangeNotifier disposal, listener cleanup, and Controller lookup patterns.

Available Rules #

Rule Description Quick Fixes
dispose_notifier ChangeNotifier subclasses created in State must be disposed Add dispose method, Add dispose call
remove_listener Listeners added to Listenables must be removed in dispose Add removeListener call
controller_listen_in_callback Controller lookups in callbacks should use listen: false Add 'listen: false'

Installation #

Add mz_lints to your pubspec.yaml:

dev_dependencies:
  mz_lints: ^0.0.1

Then enable the plugin in your analysis_options.yaml:

# Requires Dart 3.10+ / Flutter 3.38+
plugins:
  mz_lints: ^0.0.1

Rule Details #

dispose_notifier #

Ensures ChangeNotifier subclasses created in StatefulWidget State classes are disposed:

  • TextEditingController, ScrollController, AnimationController
  • TabController, PageController, FocusNode
  • ValueNotifier, and any custom ChangeNotifier subclass

BAD:

class _MyWidgetState extends State<MyWidget> {
  final _controller = TextEditingController(); // LINT: not disposed
  
  @override
  Widget build(BuildContext context) {
    return TextField(controller: _controller);
  }
}

GOOD:

class _MyWidgetState extends State<MyWidget> {
  final _controller = TextEditingController();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return TextField(controller: _controller);
  }
}

remove_listener #

Ensures listeners added in initState, didChangeDependencies, or didUpdateWidget are removed in dispose:

BAD:

class _MyWidgetState extends State<MyWidget> {
  @override
  void initState() {
    super.initState();
    widget.controller.addListener(_onChanged); // LINT: never removed
  }
  
  void _onChanged() {}
}

GOOD:

class _MyWidgetState extends State<MyWidget> {
  @override
  void initState() {
    super.initState();
    widget.controller.addListener(_onChanged);
  }

  @override
  void dispose() {
    widget.controller.removeListener(_onChanged);
    super.dispose();
  }
  
  void _onChanged() {}
}

controller_listen_in_callback #

Warns when using Controller.ofType() or similar lookup methods inside event handlers without listen: false:

BAD:

void _onButtonPressed() {
  // Will cause unnecessary rebuilds
  final controller = Controller.ofType<MyController>(context);
  controller.doSomething();
}

GOOD:

void _onButtonPressed() {
  final controller = Controller.ofType<MyController>(context, listen: false);
  controller.doSomething();
}

Suppressing Rules #

You can suppress rules using standard Dart ignore comments:

Suppress for entire file:

// ignore_for_file: dispose_notifier, remove_listener

class MyWidget extends StatefulWidget {
  // ...
}

Suppress for a single line:

class _MyWidgetState extends State<MyWidget> {
  // ignore: dispose_notifier
  final _controller = TextEditingController();
}

Requirements #

  • Dart SDK 3.10.0 or later
  • Flutter 3.38.0 or later (for Flutter projects)

This package is part of the mz_utils ecosystem.

License #

MIT License - see the LICENSE file for details.

0
likes
140
points
6
downloads

Documentation

API reference

Publisher

verified publisherkopan7.com

Weekly Downloads

Custom Dart lint rules for Flutter apps. Includes rules for proper disposal of ChangeNotifiers, listener cleanup, and Controller lookup patterns.

Topics

#lints #static-analysis #flutter #analyzer-plugin

License

MIT (license)

Dependencies

analysis_server_plugin, analyzer, analyzer_plugin

More

Packages that depend on mz_lints