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
99
downloads

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

Documentation

API reference

License

MIT (license)

Dependencies

analysis_server_plugin, analyzer, analyzer_plugin

More

Packages that depend on mz_lints