dispose-providers
- Group
- Correctness
- Path
lint/correctness/dispose-providers- Default
- On (recommended)
- Origin
- Falcon
- Domain
- provider
- Rule
- 225 of 512
Requires cleanup callbacks for disposable values created by package:provider's Provider.
The created value's inferred type must declare or inherit an instance method
named dispose, close, or cancel. Each such method must be called on the
dispose callback's value parameter, not another object or a shadowing local.
Value constructors do not own their values. Creation is proven only for direct
generative constructors or simple same-file function tear-offs returning one.
Unknown factories, non-inline cleanup, and path-sensitive guarantees are outside
this rule's scope.
Invalid
import 'package:provider/provider.dart' as p;
class Disposable {
void dispose() {}
}
class Closable {
void close() {}
}
class Cancelable {
void cancel() {}
}
class InheritedDisposable extends Disposable {}
final other = Disposable();
Disposable makeDisposable(dynamic context) => Disposable();
void examples() {
p.Provider(create: (_) => Disposable());
p.Provider(create: (_) => Closable());
p.Provider(create: (_) => Cancelable());
p.Provider(create: makeDisposable);
p.Provider(create: (_) { return Disposable(); });
new p.Provider(create: (_) => InheritedDisposable());
p.Provider(create: (_) => Disposable(), dispose: (_, value) {});
p.Provider(create: (_) => Disposable(), dispose: (_, value) => other.dispose());
p.Provider(create: (_) => Disposable(), dispose: (_, value) => value.toString());
p.Provider(create: (_) => Disposable(), dispose: (_, value) {
void later() { value.dispose(); }
});
p.Provider(create: (_) => Disposable(), dispose: (_, value) {
{ final value = other; value.dispose(); }
});
}void examples() { p.Provider(create: (_) => Disposable()); p.Provider(create: (_) => Disposable()); p.Provider(create: (_) => Closable()); p.Provider(create: (_) => Closable()); p.Provider(create: (_) => Cancelable()); p.Provider(create: (_) => Cancelable()); p.Provider(create: makeDisposable); p.Provider(create: makeDisposable); p.Provider(create: (_) { return Disposable(); }); p.Provider(create: (_) { return Disposable(); }); new p.Provider(create: (_) => InheritedDisposable()); new p.Provider(create: (_) => InheritedDisposable()); p.Provider(create: (_) => Disposable(), dispose: (_, value) {}); p.Provider(create: (_) => Disposable(), dispose: (_, value) {}); p.Provider(create: (_) => Disposable(), dispose: (_, value) => other.dispose()); p.Provider(create: (_) => Disposable(), dispose: (_, value) => other.dispose()); p.Provider(create: (_) => Disposable(), dispose: (_, value) => value.toString()); p.Provider(create: (_) => Disposable(), dispose: (_, value) => value.toString()); p.Provider(create: (_) => Disposable(), dispose: (_, value) { }); p.Provider(create: (_) => Disposable(), dispose: (_, value) {Valid
import 'package:provider/provider.dart' as p;
class Disposable {
void dispose() {}
}
class Closable {
void close() {}
}
class Cancelable {
void cancel() {}
}
class InheritedDisposable extends Disposable {}
class Plain {}
Disposable makeDisposable(dynamic context) => Disposable();
class StaticCleanup { static void dispose() {} }
final shared = Disposable();
T getIt<T>() => shared as T;
class Api extends Disposable {
Api();
factory Api.cached() => singleton;
static final singleton = Api();
static Api instance() => singleton;
}
// A local constructor with the same spelling is not a package provider.
class Provider {
Provider({required Object Function(Object?) create});
}
void examples() {
p.Provider(create: (_) => Disposable(), dispose: (_, value) => value.dispose());
p.Provider(create: (_) => Closable(), dispose: (_, value) { value.close(); });
p.Provider(create: (_) => Cancelable(), dispose: (_, value) => value.cancel());
new p.Provider(create: (_) => InheritedDisposable(), dispose: (_, value) => value.dispose());
p.Provider(create: (_) => Disposable(), dispose: (_, value) => value..dispose());
p.Provider.value(value: Disposable());
p.Provider(create: makeDisposable, dispose: (_, value) => value.dispose());
p.Provider(create: (_) { return Disposable(); }, dispose: (_, value) { value.dispose(); });
p.Provider(create: (_) => Plain());
p.Provider(create: (_) => StaticCleanup());
Provider(create: (_) => Disposable());
p.Provider(create: (_) => Disposable(), dispose: (_, value) => value!.dispose());
p.Provider(create: (_) => Disposable(), dispose: (_, value) => (value as Disposable).dispose());
final existing = Disposable();
p.Provider(create: (_) => existing);
p.Provider(create: (dynamic context) => context.read<Disposable>());
p.Provider(create: (_) => getIt<Disposable>());
p.Provider(create: (_) => Api.instance());
p.Provider(create: (_) => Api.cached());
}Configure dispose-providers
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"dispose-providers": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/dispose-providers: <reason>More correctness rules
- emit-new-bloc-state-instancesrecommendedbloc
Flags Bloc and Cubit emissions that reuse their current state instance.
- exhaustive-cases
exhaustive_casesrecommendedRequire switch statements over enum-like classes to cover every constant value.
- function-always-returns-null
Flags value functions with a proven explicit null return on every path.
- function-always-returns-same-value
Warns when distinct return paths in a function produce the same scalar constant.
- handle-bloc-event-subclassesbloc
Warns when a Bloc constructor leaves a concrete event subclass without a handler.
- hash-and-equals
hash_and_equalsrecommendedRequire
hashCodeand==to be overridden together. - implementation-imports
implementation_importsrecommendedDisallow importing another package's private
src/libraries. - implicit-reopen
implicit_reopenFlags classes that implicitly reopen a supertype declared in the same library.