proper-controller-dispose
Same as proper_controller_dispose in Pyramid Lint
- Group
- Correctness
- Path
lint/correctness/proper-controller-dispose- Default
- On (recommended)
- Origin
- Pyramid Lint
- Domain
- flutter
- Rule
- 422 of 512
Requires Flutter controllers owned by a State field to be disposed.
Shared field checks recognize eagerly evaluated releases, including arguments
and operands, but not deferred closures or conditional expression branches.
Invalid
import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as flutter;
class A extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
super.dispose();
}
}
class B extends State<StatefulWidget> {
final page = PageController();
}
class C extends State<StatefulWidget> {
late ScrollController scroll;
@override
void initState() {
super.initState();
scroll = ScrollController();
}
@override
void dispose() {
super.dispose();
}
}
class D extends State<StatefulWidget> {
final tabs = TabController(length: 2, vsync: this);
final text = TextEditingController();
@override
void dispose() {
text.dispose();
super.dispose();
}
}
class E extends State<StatefulWidget> {
late final anim = AnimationController.unbounded(vsync: this);
@override
void dispose() {
super.dispose();
}
}
class F extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
final controller = TextEditingController();
controller.dispose();
super.dispose();
}
}
class G extends State<StatefulWidget> {
final controller = TextEditingController(text: widget.initialText);
}
class H extends flutter.State<flutter.StatefulWidget> {
final controller = flutter.ScrollController();
}
class CollectionIfCaseInsideStatement extends State<StatefulWidget> {
late TextEditingController controller;
@override
void initState() {
super.initState();
if (widget case final controller?) {
final list = [if (widget case final nested?) nested];
}
controller = TextEditingController();
}
}
class ShadowedBodyDisposals extends State<StatefulWidget> {
final blockShadow = TextEditingController();
final forShadow = TextEditingController();
final patternShadow = TextEditingController();
final caseShadow = TextEditingController();
final catchShadow = TextEditingController();
final closureShadow = TextEditingController();
final functionShadow = TextEditingController();
@override
void dispose() {
{
final blockShadow = TextEditingController();
blockShadow.dispose();
}
for (final forShadow in <TextEditingController>[]) {
forShadow.dispose();
}
for (final [patternShadow] in <List<TextEditingController>>[]) {
patternShadow.dispose();
}
if (widget case TextEditingController caseShadow) {
caseShadow.dispose();
}
try {
throw widget;
} catch (catchShadow) {
catchShadow.dispose();
}
final callback = (TextEditingController closureShadow) {
closureShadow.dispose();
};
void local(TextEditingController functionShadow) {
functionShadow.dispose();
}
super.dispose();
}
}class A extends State<StatefulWidget> { final controller = TextEditingController();class B extends State<StatefulWidget> { final page = PageController();class C extends State<StatefulWidget> { late ScrollController scroll;class D extends State<StatefulWidget> { final tabs = TabController(length: 2, vsync: this);class E extends State<StatefulWidget> { late final anim = AnimationController.unbounded(vsync: this);class F extends State<StatefulWidget> { final controller = TextEditingController();class G extends State<StatefulWidget> { final controller = TextEditingController(text: widget.initialText);class H extends flutter.State<flutter.StatefulWidget> { final controller = flutter.ScrollController();class CollectionIfCaseInsideStatement extends State<StatefulWidget> { late TextEditingController controller;class ShadowedBodyDisposals extends State<StatefulWidget> { final blockShadow = TextEditingController(); final blockShadow = TextEditingController(); final forShadow = TextEditingController(); final forShadow = TextEditingController(); final patternShadow = TextEditingController(); final patternShadow = TextEditingController(); final caseShadow = TextEditingController(); final caseShadow = TextEditingController(); final catchShadow = TextEditingController(); final catchShadow = TextEditingController(); final closureShadow = TextEditingController(); final closureShadow = TextEditingController(); final functionShadow = TextEditingController();Valid
import 'package:flutter/material.dart';
class A extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
class B extends State<StatefulWidget> {
late final controller = widget.controller;
@override
void dispose() {
super.dispose();
}
}
class C extends State<StatefulWidget> {
final scroll = ScrollController();
final text = TextEditingController();
@override
void dispose() {
scroll.dispose();
text.dispose();
super.dispose();
}
}
class D {
final controller = TextEditingController();
}
class E extends State<StatefulWidget> {
TabController? tabs;
@override
void dispose() {
tabs?.dispose();
super.dispose();
}
}
class F extends State<StatefulWidget> {
final _controller = ScrollController();
@override
void dispose() {
_controller
..removeListener(_onScroll)
..dispose();
super.dispose();
}
void _onScroll() {}
}
class G extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
this.controller.dispose();
super.dispose();
}
}
class CollectionIfCases extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
final value = widget;
final list = [if (value case final controller?) controller];
final set = <Object>{if (value case final controller?) controller};
final map = <Object, Object>{
if (value case final controller?) controller: controller,
};
controller.dispose();
super.dispose();
}
}
class RestoredBodyScopes extends State<StatefulWidget> {
final controller = TextEditingController();
@override
void dispose() {
{
final controller = TextEditingController();
controller.dispose();
}
for (final controller in <TextEditingController>[]) {
controller.dispose();
}
for (final [controller] in <List<TextEditingController>>[]) {
controller.dispose();
}
if (widget case final controller?) {
final list = [if (widget case final nested?) nested];
} else {
controller.dispose();
}
try {
throw widget;
} catch (controller) {}
final callback = (TextEditingController controller) {
controller.dispose();
};
void local(TextEditingController controller) {
controller.dispose();
}
controller.dispose();
super.dispose();
}
}
class InitializerIsNotBodyOwnership extends State<StatefulWidget> {
final TextEditingController controller;
InitializerIsNotBodyOwnership() : controller = TextEditingController();
}Configure proper-controller-dispose
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"proper-controller-dispose": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/proper-controller-dispose: <reason>More correctness rules
- proper-expanded-and-flexible
proper_expanded_and_flexiblerecommendedflutterRequire
ExpandedandFlexibleto sit directly inside a flex widget. - proper-from-environment
proper_from_environmentrecommendedRequire
fromEnvironmentto be evaluated in a const context. - proper-super-init-state
proper_super_init_staterecommendedflutterRequire
super.initState()to be the first statement of a resolved FlutterStatesubclass'sinitStateoverride. - require-super-disposerecommendedflutter
Require
super.dispose()in Flutter State dispose overrides. - sort-pub-dependencies
sort_pub_dependenciescross-fileRequire
pubspec.yamldependency sections to be sorted alphabetically. - test-types-in-equals
test_types_in_equalsrecommendedFlags casting the parameter of
operator ==instead of testing its type. - throw-in-finally
throw_in_finallyrecommendedFlags
throwinside afinallyblock. - type-literal-in-constant-pattern
type_literal_in_constant_patternrecommendedDon't use constant patterns whose expressions have the core
Typetype.