avoid-undisposed-instances

Path
lint/correctness/avoid-undisposed-instances
Default
On (recommended)
Origin
Falcon
Domain
flutter
Rule
153 of 512
recommendedflutter

Warns when a disposable constructor result is discarded.

Only resolved constructors with an instance dispose method are checked. Passing a value as a call or constructor argument may transfer ownership: without a callee ownership contract, reporting it would be speculative. Reading a member or interpolating an instance does not transfer the instance. Assignments, variable initializers, returns, and immediately disposed expressions are also ignored. This conservative rule checks temporaries only; it does not prove that retained locals are eventually disposed. Owned fields belong to dispose-fields, dispose-focus-node-and-timer, or proper-controller-dispose. Subscription and sink release obligations remain with cancel-subscriptions and close-sinks.

Invalid

example.dartdart
import 'package:flutter/material.dart';
class Resource { void dispose() {} }
void bad() {
 TextEditingController();
 ScrollController();
 FocusNode();
 Resource();
 new Resource();
}
void consume(Object value) {}
void discardedInsideCallback() {
 consume(() {
  Resource();
 });
}
void discardedArgumentReceivers() {
 print(ScrollController().initialScrollOffset);
 consume(FocusNode().hasFocus);
 Text('${Resource()}');
}
Retain this disposable instance and dispose it when its owner is released.
3void bad() {
4 TextEditingController();
Retain this disposable instance and dispose it when its owner is released.
4 TextEditingController();
5 ScrollController();
Retain this disposable instance and dispose it when its owner is released.
5 ScrollController();
6 FocusNode();
Retain this disposable instance and dispose it when its owner is released.
6 FocusNode();
7 Resource();
Retain this disposable instance and dispose it when its owner is released.
7 Resource();
8 new Resource();
Retain this disposable instance and dispose it when its owner is released.
12 consume(() {
13 Resource();
Retain this disposable instance and dispose it when its owner is released.
16void discardedArgumentReceivers() {
17 print(ScrollController().initialScrollOffset);
Retain this disposable instance and dispose it when its owner is released.
17 print(ScrollController().initialScrollOffset);
18 consume(FocusNode().hasFocus);
Retain this disposable instance and dispose it when its owner is released.
18 consume(FocusNode().hasFocus);
19 Text('${Resource()}');

Valid

example.dartdart
import 'package:flutter/material.dart';
class Resource {
 void dispose() {}
 static Resource shared() => Resource();
}
class Owner { final resource = Resource(); }
Resource create() => Resource();
Resource createBlock() { return Resource(); }
void consume(Object value) {}
void good() {
 final a = TextEditingController();
 var b = Resource();
 b = Resource();
 Resource()..dispose();
 consume('not disposable');
 a.dispose();
 b.dispose();
}
class InitializedOwner {
 final Resource resource;
 InitializedOwner() : resource = Resource();
}
void wrappers(bool flag, Resource? borrowed) {
 final either = flag ? Resource() : Resource();
 final effective = borrowed ?? Resource();
 final nodes = [FocusNode(), FocusNode()];
 Resource().dispose();
 Resource.shared();
}
void shadowedConstructor() {
 final FocusNode = () => Object();
 consume(FocusNode());
}

void transferredArguments(BuildContext context) {
 Navigator.push(context, MaterialPageRoute<void>(builder: (_) => const SizedBox()));
 consume(TextEditingController());
 consume(ScrollController());
 consume(FocusNode());
 consume(Resource());
 consume(new Resource());
 consume((Resource()));
 consume(Resource()..toString());
 final resource = Resource();
 consume(resource);
 final sink = HiveLogSink();
 LoggerService._(sink: sink);
 LoggerService._(sink: HiveLogSink());
}

class HiveLogSink {
 void dispose() {}
}

class LoggerService {
 final HiveLogSink sink;
 LoggerService._({required this.sink});
}

Configure avoid-undisposed-instances

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-undisposed-instances": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/avoid-undisposed-instances: <reason>