Skip to content

Commit c6b636f

Browse files
[flutter_tools] Replace Future.catchError() with Future.then(onError: ...) (flutter#120637)
* wip run_local_linter.dart * get run_local_linter.dart working * slow working implementation * speed up run_local_linter.dart * fix run_local_linter.dart * remove catchError * another fix * fix another * fix * more fixes * fix moar * fix moar * fix * finish * fix tests * clean up further * code review * delete run_local_linter.dart
1 parent 8d15083 commit c6b636f

File tree

13 files changed

+188
-108
lines changed

13 files changed

+188
-108
lines changed

packages/flutter_tools/lib/src/commands/daemon.dart

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,12 @@ class _DaemonServer {
123123
// We have to listen to socket.done. Otherwise when the connection is
124124
// reset, we will receive an uncatchable exception.
125125
// https://github.com/dart-lang/sdk/issues/25518
126-
final Future<void> socketDone = socket.done.catchError((Object error, StackTrace stackTrace) {
127-
logger.printError('Socket error: $error');
128-
logger.printTrace('$stackTrace');
129-
});
126+
final Future<void> socketDone = socket.done.then<void>(
127+
(_) {},
128+
onError: (Object error, StackTrace stackTrace) {
129+
logger.printError('Socket error: $error');
130+
logger.printTrace('$stackTrace');
131+
});
130132
final Daemon daemon = Daemon(
131133
DaemonConnection(
132134
daemonStreams: DaemonStreams.fromSocket(socket, logger: logger),
@@ -278,7 +280,7 @@ abstract class Domain {
278280
}).then<Object?>((Object? result) {
279281
daemon.connection.sendResponse(id, _toJsonable(result));
280282
return null;
281-
}).catchError((Object error, StackTrace stackTrace) {
283+
}, onError: (Object error, StackTrace stackTrace) {
282284
daemon.connection.sendErrorResponse(id, _toJsonable(error), stackTrace);
283285
return null;
284286
});
@@ -1418,7 +1420,9 @@ class ProxyDomain extends Domain {
14181420
globals.logger.printTrace('Socket error: $error, $stackTrace');
14191421
});
14201422

1421-
unawaited(socket.done.catchError((Object error, StackTrace stackTrace) {
1423+
unawaited(socket.done.then<Object?>(
1424+
(Object? obj) => obj,
1425+
onError: (Object error, StackTrace stackTrace) {
14221426
// Socket error, probably disconnected.
14231427
globals.logger.printTrace('Socket error: $error, $stackTrace');
14241428
}).then((Object? _) {

packages/flutter_tools/lib/src/commands/validate_project.dart

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,17 @@ class ValidateProject {
4242
continue;
4343
}
4444
if (!results.containsKey(validator) && validator.supportsProject(project)) {
45-
results[validator] = validator.start(project).catchError((Object exception, StackTrace trace) {
46-
hasCrash = true;
47-
return <ProjectValidatorResult>[ProjectValidatorResult.crash(exception, trace)];
48-
});
45+
results[validator] = validator
46+
.start(project)
47+
.then(
48+
(List<ProjectValidatorResult> results) => results,
49+
onError: (Object exception, StackTrace trace) {
50+
hasCrash = true;
51+
return <ProjectValidatorResult>[
52+
ProjectValidatorResult.crash(exception, trace),
53+
];
54+
},
55+
);
4956
}
5057
}
5158

packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,8 +507,10 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
507507
final Completer<Object?> completer = Completer<Object?>();
508508
_reverseRequestCompleters[id] = completer;
509509
completer.future
510-
.then((Object? value) => sendResponseToFlutter(id, value))
511-
.catchError((Object? e) => sendResponseToFlutter(id, e.toString(), error: true));
510+
.then(
511+
(Object? value) => sendResponseToFlutter(id, value),
512+
onError: (Object? e) => sendResponseToFlutter(id, e.toString(), error: true),
513+
);
512514

513515
if (_requestsToForwardToClient.contains(method)) {
514516
// Forward the request to the client in an event.

packages/flutter_tools/lib/src/proxied_devices/devices.dart

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -513,40 +513,54 @@ class ProxiedPortForwarder extends DevicePortForwarder {
513513
final Stream<List<int>> dataStream = connection.listenToEvent('proxy.data.$id').asyncExpand((DaemonEventData event) => event.binary);
514514
dataStream.listen(socket.add);
515515
final Future<DaemonEventData> disconnectFuture = connection.listenToEvent('proxy.disconnected.$id').first;
516-
unawaited(disconnectFuture.then((_) {
517-
socket.close();
518-
}).catchError((_) {
519-
// The event is not guaranteed to be sent if we initiated the disconnection.
520-
// Do nothing here.
521-
}));
516+
unawaited(disconnectFuture.then<void>((_) async {
517+
try {
518+
await socket.close();
519+
} on Exception {
520+
// ignore
521+
}
522+
},
523+
onError: (_) {
524+
// The event is not guaranteed to be sent if we initiated the disconnection.
525+
// Do nothing here.
526+
},
527+
));
522528
socket.listen((Uint8List data) {
523529
unawaited(connection.sendRequest('proxy.write', <String, Object>{
524530
'id': id,
525-
}, data).catchError((Object error, StackTrace stackTrace) {
526-
// Log the error, but proceed normally. Network failure should not
527-
// crash the tool. If this is critical, the place where the connection
528-
// is being used would crash.
529-
_logger.printWarning('Write to remote proxy error: $error');
530-
_logger.printTrace('Write to remote proxy error: $error, stack trace: $stackTrace');
531-
return null;
532-
}));
531+
}, data).then(
532+
(Object? obj) => obj,
533+
onError: (Object error, StackTrace stackTrace) {
534+
// Log the error, but proceed normally. Network failure should not
535+
// crash the tool. If this is critical, the place where the connection
536+
// is being used would crash.
537+
_logger.printWarning('Write to remote proxy error: $error');
538+
_logger.printTrace('Write to remote proxy error: $error, stack trace: $stackTrace');
539+
return null;
540+
},
541+
));
533542
});
534543
_connectedSockets.add(socket);
535544

536-
unawaited(socket.done.catchError((Object error, StackTrace stackTrace) {
545+
unawaited(socket.done.then(
546+
(Object? obj) => obj,
547+
onError: (Object error, StackTrace stackTrace) {
537548
// Do nothing here. Everything will be handled in the `then` block below.
538549
return false;
539550
}).whenComplete(() {
540551
// Send a proxy disconnect event just in case.
541552
unawaited(connection.sendRequest('proxy.disconnect', <String, Object>{
542553
'id': id,
543-
}).catchError((Object error, StackTrace stackTrace) {
544-
// Ignore the error here. There might be a race condition when the
545-
// remote end also disconnects. In any case, this request is just to
546-
// notify the remote end to disconnect and we should not crash when
547-
// there is an error here.
548-
return null;
549-
}));
554+
}).then(
555+
(Object? obj) => obj,
556+
onError: (Object error, StackTrace stackTrace) {
557+
// Ignore the error here. There might be a race condition when the
558+
// remote end also disconnects. In any case, this request is just to
559+
// notify the remote end to disconnect and we should not crash when
560+
// there is an error here.
561+
return null;
562+
},
563+
));
550564
_connectedSockets.remove(socket);
551565
}));
552566
}, onError: (Object error, StackTrace stackTrace) {

packages/flutter_tools/lib/src/run_hot.dart

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,13 @@ class HotRunner extends ResidentRunner {
523523
// We ignore any errors, because it's not clear what we would do anyway.
524524
futures.add(device.devFS!.destroy()
525525
.timeout(const Duration(milliseconds: 250))
526-
.catchError((Object? error) {
527-
globals.printTrace('Ignored error while cleaning up DevFS: $error');
528-
}));
526+
.then<void>(
527+
(Object? _) {},
528+
onError: (Object? error, StackTrace stackTrace) {
529+
globals.printTrace('Ignored error while cleaning up DevFS: $error\n$stackTrace');
530+
}
531+
),
532+
);
529533
}
530534
device.devFS = null;
531535
}
@@ -639,16 +643,22 @@ class HotRunner extends ResidentRunner {
639643
// Since we never check the value of this Future, only await its
640644
// completion, make its type nullable so we can return null when
641645
// catching errors.
642-
.then<vm_service.Success?>((vm_service.Success success) => success)
643-
.catchError((dynamic error, StackTrace stackTrace) {
644-
// Do nothing on a SentinelException since it means the isolate
645-
// has already been killed.
646-
// Error code 105 indicates the isolate is not yet runnable, and might
647-
// be triggered if the tool is attempting to kill the asset parsing
648-
// isolate before it has finished starting up.
649-
return null;
650-
}, test: (dynamic error) => error is vm_service.SentinelException
651-
|| (error is vm_service.RPCError && error.code == 105)));
646+
.then<vm_service.Success?>(
647+
(vm_service.Success success) => success,
648+
onError: (Object error, StackTrace stackTrace) {
649+
if (error is vm_service.SentinelException ||
650+
(error is vm_service.RPCError && error.code == 105)) {
651+
// Do nothing on a SentinelException since it means the isolate
652+
// has already been killed.
653+
// Error code 105 indicates the isolate is not yet runnable, and might
654+
// be triggered if the tool is attempting to kill the asset parsing
655+
// isolate before it has finished starting up.
656+
return null;
657+
}
658+
return Future<vm_service.Success?>.error(error, stackTrace);
659+
},
660+
),
661+
);
652662
}
653663
}
654664
await Future.wait(operations);
@@ -1309,10 +1319,16 @@ Future<ReassembleResult> _defaultReassembleHelper(
13091319
isolateId: view.uiIsolate!.id!,
13101320
);
13111321
}
1312-
reassembleFutures.add(reassembleWork.catchError((dynamic error) {
1313-
failedReassemble = true;
1314-
globals.printError('Reassembling ${view.uiIsolate!.name} failed: $error');
1315-
}, test: (dynamic error) => error is Exception));
1322+
reassembleFutures.add(reassembleWork.then(
1323+
(Object? obj) => obj,
1324+
onError: (Object error, StackTrace stackTrace) {
1325+
if (error is! Exception) {
1326+
return Future<Object?>.error(error, stackTrace);
1327+
}
1328+
failedReassemble = true;
1329+
globals.printError('Reassembling ${view.uiIsolate!.name} failed: $error\n$stackTrace');
1330+
},
1331+
));
13161332
}
13171333
}
13181334
}

packages/flutter_tools/lib/src/test/coverage_collector.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,16 @@ class CoverageCollector extends TestWatcher {
129129

130130
final Stopwatch? collectTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageCollect);
131131

132-
final Future<void> processComplete = testDevice.finished.catchError(
133-
(Object error) => throw Exception(
134-
'Failed to collect coverage, test device terminated prematurely with '
135-
'error: ${(error as TestDeviceException).message}.'),
136-
test: (Object error) => error is TestDeviceException,
132+
final Future<void> processComplete = testDevice.finished.then(
133+
(Object? obj) => obj,
134+
onError: (Object error, StackTrace stackTrace) {
135+
if (error is TestDeviceException) {
136+
throw Exception(
137+
'Failed to collect coverage, test device terminated prematurely with '
138+
'error: ${error.message}.\n$stackTrace');
139+
}
140+
return Future<Object?>.error(error, stackTrace);
141+
}
137142
);
138143

139144
final Future<void> collectionComplete = testDevice.vmServiceUri

packages/flutter_tools/lib/src/test/flutter_web_platform.dart

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -680,25 +680,33 @@ class BrowserManager {
680680
);
681681
final Completer<BrowserManager> completer = Completer<BrowserManager>();
682682

683-
unawaited(chrome.onExit.then<Object?>((int? browserExitCode) {
684-
throwToolExit('${runtime.name} exited with code $browserExitCode before connecting.');
685-
}).catchError((Object error, StackTrace stackTrace) {
686-
if (!completer.isCompleted) {
687-
completer.completeError(error, stackTrace);
688-
}
689-
return null;
690-
}));
691-
unawaited(future.then((WebSocketChannel webSocket) {
692-
if (completer.isCompleted) {
693-
return;
694-
}
695-
completer.complete(BrowserManager._(chrome, runtime, webSocket));
696-
}).catchError((Object error, StackTrace stackTrace) {
697-
chrome.close();
698-
if (!completer.isCompleted) {
699-
completer.completeError(error, stackTrace);
700-
}
701-
}));
683+
unawaited(chrome.onExit.then<Object?>(
684+
(int? browserExitCode) {
685+
throwToolExit('${runtime.name} exited with code $browserExitCode before connecting.');
686+
},
687+
).then(
688+
(Object? obj) => obj,
689+
onError: (Object error, StackTrace stackTrace) {
690+
if (!completer.isCompleted) {
691+
completer.completeError(error, stackTrace);
692+
}
693+
return null;
694+
},
695+
));
696+
unawaited(future.then(
697+
(WebSocketChannel webSocket) {
698+
if (completer.isCompleted) {
699+
return;
700+
}
701+
completer.complete(BrowserManager._(chrome, runtime, webSocket));
702+
},
703+
onError: (Object error, StackTrace stackTrace) {
704+
chrome.close();
705+
if (!completer.isCompleted) {
706+
completer.completeError(error, stackTrace);
707+
}
708+
},
709+
));
702710

703711
return completer.future;
704712
}

packages/flutter_tools/lib/src/vmservice.dart

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,17 @@ Future<vm_service.VmService> setUpVmService(
287287
vmService.onExtensionEvent.listen(printStructuredErrorLogMethod);
288288
registrationRequests.add(vmService
289289
.streamListen(vm_service.EventStreams.kExtension)
290-
.then<vm_service.Success?>((vm_service.Success success) => success)
291-
// It is safe to ignore this error because we expect an error to be
292-
// thrown if we're already subscribed.
293-
.catchError((Object? error) => null, test: (Object? error) => error is vm_service.RPCError)
290+
.then<vm_service.Success?>(
291+
(vm_service.Success success) => success,
292+
// It is safe to ignore this error because we expect an error to be
293+
// thrown if we're already subscribed.
294+
onError: (Object error, StackTrace stackTrace) {
295+
if (error is vm_service.RPCError) {
296+
return null;
297+
}
298+
return Future<vm_service.Success?>.error(error, stackTrace);
299+
},
300+
),
294301
);
295302
}
296303

@@ -971,14 +978,16 @@ class FlutterVmService {
971978
/// been collected.
972979
Future<vm_service.Isolate?> getIsolateOrNull(String isolateId) async {
973980
return service.getIsolate(isolateId)
974-
// The .then() call is required to cast from Future<Isolate> to Future<Isolate?>
975-
.then<vm_service.Isolate?>((vm_service.Isolate isolate) => isolate)
976-
.catchError((Object? error, StackTrace stackTrace) {
977-
return null;
978-
}, test: (Object? error) {
979-
return (error is vm_service.SentinelException) ||
980-
(error is vm_service.RPCError && error.code == RPCErrorCodes.kServiceDisappeared);
981-
});
981+
.then<vm_service.Isolate?>(
982+
(vm_service.Isolate isolate) => isolate,
983+
onError: (Object? error, StackTrace stackTrace) {
984+
if (error is vm_service.SentinelException ||
985+
error == null ||
986+
(error is vm_service.RPCError && error.code == RPCErrorCodes.kServiceDisappeared)) {
987+
return null;
988+
}
989+
return Future<vm_service.Isolate?>.error(error, stackTrace);
990+
});
982991
}
983992

984993
/// Create a new development file system on the device.

packages/flutter_tools/test/general.shard/base/async_guard_test.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,12 @@ void main() {
164164
await FakeAsync().run((FakeAsync time) {
165165
unawaited(runZonedGuarded(() async {
166166
final Future<void> f = asyncGuard<void>(() => delayedThrow(time))
167-
.catchError((Object e, StackTrace s) {
168-
caughtByCatchError = true;
169-
});
167+
.then(
168+
(Object? obj) => obj,
169+
onError: (Object e, StackTrace s) {
170+
caughtByCatchError = true;
171+
},
172+
);
170173
try {
171174
await f;
172175
} on _CustomException {

packages/flutter_tools/test/general.shard/base/task_queue_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ void main() {
5454
final Set<int> completed = <int>{};
5555
final TaskQueue<void> tracker = TaskQueue<void>(maxJobs: 1);
5656
await tracker.add(() async => completed.add(0));
57-
await tracker.add(() async => throw TestException()).catchError((Object _) {});
58-
await tracker.add(() async => throw TestException()).catchError((Object _) {});
57+
await tracker.add(() async => throw TestException()).then((_) {}, onError: (Object _) {});
58+
await tracker.add(() async => throw TestException()).then((_) {}, onError: (Object _) {});
5959
await tracker.add(() async => completed.add(3));
6060
await tracker.tasksComplete;
6161
expect(completed.length, equals(2));

0 commit comments

Comments
 (0)