dispose-provided-instances

Path
lint/correctness/dispose-provided-instances
Default
On (recommended)
Origin
Falcon
Domain
riverpod
Rule
223 of 512
recommendedriverpod

Flags provider-created instances with a dispose method that lack ref.onDispose cleanup.

Riverpod autoDispose destroys provider state, not arbitrary disposable objects. Register each owned instance's dispose method with the provider's ref.onDispose. Only package-confirmed Provider/FutureProvider/StreamProvider callbacks and resolved constructor-created resources are checked. Nested deferred closures, borrowed values, unknown types, and types without a recognized release method are excluded. Direct cleanup and named local callbacks are recognized; opaque cleanup calls mentioning the resource conservatively count as registration. Borrowed factory returns are recognized only when their simple body is visible in this file; constructor metadata does not expose bodies from other libraries.

Invalid

example.dartdart
import 'package:riverpod/riverpod.dart';

class Service {
  Service();
  Service.named();
  void dispose() {}
}
class Child extends Service {}

final plain = Provider((ref) {
  final service = Service();
  return service;
});
final automatic = Provider.autoDispose((ref) {
  final service = Service();
  return service;
});
final arrow = Provider((ref) => Service());
final explicitNew = Provider((ref) {
  final service = new Service();
  return service;
});
final named = Provider((ref) {
  final service = Service.named();
  return service;
});
final inherited = Provider((ref) {
  final service = Child();
  return service;
});
final wrongInstance = Provider((ref) {
  final owned = Service();
  ref.onDispose(() {});
  return owned;
});
final mereMention = Provider((ref) {
  final service = Service();
  ref.onDispose(() { service.dispose; });
  return service;
});
final deferred = Provider((ref) {
  final service = Service();
  ref.onDispose(() { final later = () => service.dispose(); });
  return service;
});
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
10final plain = Provider((ref) {
11 final service = Service();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
14final automatic = Provider.autoDispose((ref) {
15 final service = Service();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
17});
18final arrow = Provider((ref) => Service());
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
19final explicitNew = Provider((ref) {
20 final service = new Service();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
23final named = Provider((ref) {
24 final service = Service.named();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
27final inherited = Provider((ref) {
28 final service = Child();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
31final wrongInstance = Provider((ref) {
32 final owned = Service();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
36final mereMention = Provider((ref) {
37 final service = Service();
Register this instance's `dispose` method with `ref.onDispose`; `autoDispose` does not dispose the instance.
41final deferred = Provider((ref) {
42 final service = Service();

Valid

example.dartdart
import 'package:riverpod/riverpod.dart';

class Service { Service(); void dispose() {} }
class Value { Value(); }
final shared = Service();
final tearOff = Provider((ref) {
  final service = Service();
  ref.onDispose(service.dispose);
  return service;
});
final arrowCleanup = Provider((ref) {
  final service = Service();
  ref.onDispose(() => service.dispose());
  return service;
});
final blockCleanup = Provider.autoDispose((ref) {
  final service = Service();
  ref.onDispose(() { service.dispose(); });
  return service;
});
final borrowed = Provider((ref) => shared);
final immutable = Provider((ref) => Value());
final deferred = Provider((ref) => () => Service());
final twoInstances = Provider((ref) {
  final first = Service();
  final second = Service();
  ref.onDispose(first.dispose);
  ref.onDispose(() { second.dispose(); });
  return first;
});
Service outsideProvider() => Service();
void ordinaryCallback(Object Function(Ref) callback) {}
void unrelatedApi() { ordinaryCallback((ref) => Service()); }

Configure dispose-provided-instances

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "dispose-provided-instances": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/correctness/dispose-provided-instances: <reason>