-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: use_build_context_synchronously
should lint unsafe usages of sync then(), catchError() and whenComplete() callbacks
#4923
Comments
use_build_context_synchronously
should lint unsafe usages inside then(), catchError() and whenComplete()use_build_context_synchronously
should lint unsafe usages of sync then(), catchError() and whenComplete() callbacks
I agree with the issue author. Ideally, we'd warn in those cases as well. |
What is the triggering condition here? A function literal inside a void f(int value) {
Navigator.of(context).pop();
}
Future<int>.delayed(Duration(seconds: 1), (_) {
return 42;
}).then(f); In static analysis we cannot track how functions are called through an arbitrary number of functions. It would not be hard to just trigger on function literals passed to |
This would already be a big step in the right direction. |
That's similar to how the rule works today for the async/await case, right? For example, in the following code you will not get any lints on the problematic use of await future;
methodThatWillUseContext(); So, I think just warning on this in function literals would be a good idea and match what we do in other cases. |
That's right. I hadn't thought about how this request mirrors the existing code pretty well, and the same limitation would apply. This should be technically simple, but we'll see where the dragons lie when applying it to the flutter repos :D |
This could potentially apply to gobs of Dart SDK function callbacks. Here's what I've got so far:
|
Fixes dart-lang/linter#4923 In this change we now protect code inside callback arguments to functions like `Future.then`. For example: ```dart Future<int>.delayed(Duration(seconds: 1), (_) { return 42; }).then((int value) { Navigator.of(context).pop(); }); ``` In code like this, each reference to BuildContext must be guarded by a mounted check. There are a number of "protected functions" that the rule now checks: Constructors: * Future.new: 1st positional parameter * Future.delayed: 2nd positional parameter * Future.microtask: 1st positional parameter * Stream.eventTransformed: 2nd positional parameter * Stream.multi: 1st positional parameter * Stream.periodic: 2nd positional parameter * StreamController.new: 'onListen', 'onPause', 'onResume', and 'onCancel' named parameters * StreamController.broadcast: 'onListen' and 'onCancel' named parameters Instance Methods: * Future.catchError: first positional parameter, and 'test' named parameter * Future.onError: 1st positional parameter, and 'test' named parameter * Future.then: 1st positional parameter, and 'onError' named parameter * Future.timeout: 'onTimeout' named parameter * Future.whenComplete: 1st positional parameter * Stream.any: 1st positional parameter * Stream.asBroadcastStream: 'onListen' and 'onCancel' named parameters * Stream.asyncExpand: 1st positional parameter * Stream.asyncMap: 1st positional parameter * Stream.distinct: 1st positional parameter * Stream.expand: 1st positional parameter * Stream.firstWhere: first positional parameter, and 'orElse' named parameter * Stream.fold: second positional parameter * Stream.forEach: 1st positional parameter * Stream.handleError: 1st positional parameter, and 'test' named parameter * Stream.lastWhere: 1st positional parameter, and 'orElse' named parameter * Stream.listen: 1st positional parameter, and 'onError' and 'onDone' named parameters * Stream.map: 1st positional parameter * Stream.reduce: 1st positional parameter * Stream.singleWhere: 1st positional parameter, and 'orElse' named parameter * Stream.skipWhile: 1st positional parameter * Stream.takeWhile: 1st positional parameter * Stream.timeout: 'onTimeout' named parameter * Stream.where: 1st positional parameter * Stream.onData: 1st positional parameter * Stream.onDone: 1st positional parameter * Stream.onError: 1st positional parameter Static Methods: * Future.doWhile: 1st positional parameter * Future.forEach: 2nd positional parameter * Future.wait: 'cleanUp' named parameter Change-Id: I703d5cfbee5e8af1f703f40046832d66b9b59bc2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365541 Reviewed-by: Phil Quitslund <pquitslund@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
Fixed with dart-lang/sdk@a6762dd |
use_build_context_synchronously
Description
"Don't use BuildContexts across async gaps inside Future callbacks" (This wording can definitely be better)
Details
Currently the
use_build_context_synchronously
warns if a BuildContext is used after an await, without a mounted check on said context. The same rule also applies to uses insideFuture.then()
,Future.catchError()
andFuture.whenComplete()
, but only if said functions use awaits themselves.A developer could write code using the
then/catchError/whenComplete
callbacks and not use anyasync/await
keyword at all, but the underlying rule still applies.I filed #4892 in the past, where I did mention the callbacks as well, but for
setState((){})
uses.Kind
This enhancement would guard against errors.
Bad Examples
Good Examples
Discussion
Add any other motivation or useful context here.
Discussion checklist
The text was updated successfully, but these errors were encountered: