Unverified Commit c6b636fa authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] Replace Future.catchError() with Future.then(onError: ...) (#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
parent 8d150833
...@@ -123,10 +123,12 @@ class _DaemonServer { ...@@ -123,10 +123,12 @@ class _DaemonServer {
// We have to listen to socket.done. Otherwise when the connection is // We have to listen to socket.done. Otherwise when the connection is
// reset, we will receive an uncatchable exception. // reset, we will receive an uncatchable exception.
// https://github.com/dart-lang/sdk/issues/25518 // https://github.com/dart-lang/sdk/issues/25518
final Future<void> socketDone = socket.done.catchError((Object error, StackTrace stackTrace) { final Future<void> socketDone = socket.done.then<void>(
logger.printError('Socket error: $error'); (_) {},
logger.printTrace('$stackTrace'); onError: (Object error, StackTrace stackTrace) {
}); logger.printError('Socket error: $error');
logger.printTrace('$stackTrace');
});
final Daemon daemon = Daemon( final Daemon daemon = Daemon(
DaemonConnection( DaemonConnection(
daemonStreams: DaemonStreams.fromSocket(socket, logger: logger), daemonStreams: DaemonStreams.fromSocket(socket, logger: logger),
...@@ -278,7 +280,7 @@ abstract class Domain { ...@@ -278,7 +280,7 @@ abstract class Domain {
}).then<Object?>((Object? result) { }).then<Object?>((Object? result) {
daemon.connection.sendResponse(id, _toJsonable(result)); daemon.connection.sendResponse(id, _toJsonable(result));
return null; return null;
}).catchError((Object error, StackTrace stackTrace) { }, onError: (Object error, StackTrace stackTrace) {
daemon.connection.sendErrorResponse(id, _toJsonable(error), stackTrace); daemon.connection.sendErrorResponse(id, _toJsonable(error), stackTrace);
return null; return null;
}); });
...@@ -1418,7 +1420,9 @@ class ProxyDomain extends Domain { ...@@ -1418,7 +1420,9 @@ class ProxyDomain extends Domain {
globals.logger.printTrace('Socket error: $error, $stackTrace'); globals.logger.printTrace('Socket error: $error, $stackTrace');
}); });
unawaited(socket.done.catchError((Object error, StackTrace stackTrace) { unawaited(socket.done.then<Object?>(
(Object? obj) => obj,
onError: (Object error, StackTrace stackTrace) {
// Socket error, probably disconnected. // Socket error, probably disconnected.
globals.logger.printTrace('Socket error: $error, $stackTrace'); globals.logger.printTrace('Socket error: $error, $stackTrace');
}).then((Object? _) { }).then((Object? _) {
......
...@@ -42,10 +42,17 @@ class ValidateProject { ...@@ -42,10 +42,17 @@ class ValidateProject {
continue; continue;
} }
if (!results.containsKey(validator) && validator.supportsProject(project)) { if (!results.containsKey(validator) && validator.supportsProject(project)) {
results[validator] = validator.start(project).catchError((Object exception, StackTrace trace) { results[validator] = validator
hasCrash = true; .start(project)
return <ProjectValidatorResult>[ProjectValidatorResult.crash(exception, trace)]; .then(
}); (List<ProjectValidatorResult> results) => results,
onError: (Object exception, StackTrace trace) {
hasCrash = true;
return <ProjectValidatorResult>[
ProjectValidatorResult.crash(exception, trace),
];
},
);
} }
} }
......
...@@ -507,8 +507,10 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter { ...@@ -507,8 +507,10 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
final Completer<Object?> completer = Completer<Object?>(); final Completer<Object?> completer = Completer<Object?>();
_reverseRequestCompleters[id] = completer; _reverseRequestCompleters[id] = completer;
completer.future completer.future
.then((Object? value) => sendResponseToFlutter(id, value)) .then(
.catchError((Object? e) => sendResponseToFlutter(id, e.toString(), error: true)); (Object? value) => sendResponseToFlutter(id, value),
onError: (Object? e) => sendResponseToFlutter(id, e.toString(), error: true),
);
if (_requestsToForwardToClient.contains(method)) { if (_requestsToForwardToClient.contains(method)) {
// Forward the request to the client in an event. // Forward the request to the client in an event.
......
...@@ -513,40 +513,54 @@ class ProxiedPortForwarder extends DevicePortForwarder { ...@@ -513,40 +513,54 @@ class ProxiedPortForwarder extends DevicePortForwarder {
final Stream<List<int>> dataStream = connection.listenToEvent('proxy.data.$id').asyncExpand((DaemonEventData event) => event.binary); final Stream<List<int>> dataStream = connection.listenToEvent('proxy.data.$id').asyncExpand((DaemonEventData event) => event.binary);
dataStream.listen(socket.add); dataStream.listen(socket.add);
final Future<DaemonEventData> disconnectFuture = connection.listenToEvent('proxy.disconnected.$id').first; final Future<DaemonEventData> disconnectFuture = connection.listenToEvent('proxy.disconnected.$id').first;
unawaited(disconnectFuture.then((_) { unawaited(disconnectFuture.then<void>((_) async {
socket.close(); try {
}).catchError((_) { await socket.close();
// The event is not guaranteed to be sent if we initiated the disconnection. } on Exception {
// Do nothing here. // ignore
})); }
},
onError: (_) {
// The event is not guaranteed to be sent if we initiated the disconnection.
// Do nothing here.
},
));
socket.listen((Uint8List data) { socket.listen((Uint8List data) {
unawaited(connection.sendRequest('proxy.write', <String, Object>{ unawaited(connection.sendRequest('proxy.write', <String, Object>{
'id': id, 'id': id,
}, data).catchError((Object error, StackTrace stackTrace) { }, data).then(
// Log the error, but proceed normally. Network failure should not (Object? obj) => obj,
// crash the tool. If this is critical, the place where the connection onError: (Object error, StackTrace stackTrace) {
// is being used would crash. // Log the error, but proceed normally. Network failure should not
_logger.printWarning('Write to remote proxy error: $error'); // crash the tool. If this is critical, the place where the connection
_logger.printTrace('Write to remote proxy error: $error, stack trace: $stackTrace'); // is being used would crash.
return null; _logger.printWarning('Write to remote proxy error: $error');
})); _logger.printTrace('Write to remote proxy error: $error, stack trace: $stackTrace');
return null;
},
));
}); });
_connectedSockets.add(socket); _connectedSockets.add(socket);
unawaited(socket.done.catchError((Object error, StackTrace stackTrace) { unawaited(socket.done.then(
(Object? obj) => obj,
onError: (Object error, StackTrace stackTrace) {
// Do nothing here. Everything will be handled in the `then` block below. // Do nothing here. Everything will be handled in the `then` block below.
return false; return false;
}).whenComplete(() { }).whenComplete(() {
// Send a proxy disconnect event just in case. // Send a proxy disconnect event just in case.
unawaited(connection.sendRequest('proxy.disconnect', <String, Object>{ unawaited(connection.sendRequest('proxy.disconnect', <String, Object>{
'id': id, 'id': id,
}).catchError((Object error, StackTrace stackTrace) { }).then(
// Ignore the error here. There might be a race condition when the (Object? obj) => obj,
// remote end also disconnects. In any case, this request is just to onError: (Object error, StackTrace stackTrace) {
// notify the remote end to disconnect and we should not crash when // Ignore the error here. There might be a race condition when the
// there is an error here. // remote end also disconnects. In any case, this request is just to
return null; // notify the remote end to disconnect and we should not crash when
})); // there is an error here.
return null;
},
));
_connectedSockets.remove(socket); _connectedSockets.remove(socket);
})); }));
}, onError: (Object error, StackTrace stackTrace) { }, onError: (Object error, StackTrace stackTrace) {
......
...@@ -523,9 +523,13 @@ class HotRunner extends ResidentRunner { ...@@ -523,9 +523,13 @@ class HotRunner extends ResidentRunner {
// We ignore any errors, because it's not clear what we would do anyway. // We ignore any errors, because it's not clear what we would do anyway.
futures.add(device.devFS!.destroy() futures.add(device.devFS!.destroy()
.timeout(const Duration(milliseconds: 250)) .timeout(const Duration(milliseconds: 250))
.catchError((Object? error) { .then<void>(
globals.printTrace('Ignored error while cleaning up DevFS: $error'); (Object? _) {},
})); onError: (Object? error, StackTrace stackTrace) {
globals.printTrace('Ignored error while cleaning up DevFS: $error\n$stackTrace');
}
),
);
} }
device.devFS = null; device.devFS = null;
} }
...@@ -639,16 +643,22 @@ class HotRunner extends ResidentRunner { ...@@ -639,16 +643,22 @@ class HotRunner extends ResidentRunner {
// Since we never check the value of this Future, only await its // Since we never check the value of this Future, only await its
// completion, make its type nullable so we can return null when // completion, make its type nullable so we can return null when
// catching errors. // catching errors.
.then<vm_service.Success?>((vm_service.Success success) => success) .then<vm_service.Success?>(
.catchError((dynamic error, StackTrace stackTrace) { (vm_service.Success success) => success,
// Do nothing on a SentinelException since it means the isolate onError: (Object error, StackTrace stackTrace) {
// has already been killed. if (error is vm_service.SentinelException ||
// Error code 105 indicates the isolate is not yet runnable, and might (error is vm_service.RPCError && error.code == 105)) {
// be triggered if the tool is attempting to kill the asset parsing // Do nothing on a SentinelException since it means the isolate
// isolate before it has finished starting up. // has already been killed.
return null; // Error code 105 indicates the isolate is not yet runnable, and might
}, test: (dynamic error) => error is vm_service.SentinelException // be triggered if the tool is attempting to kill the asset parsing
|| (error is vm_service.RPCError && error.code == 105))); // isolate before it has finished starting up.
return null;
}
return Future<vm_service.Success?>.error(error, stackTrace);
},
),
);
} }
} }
await Future.wait(operations); await Future.wait(operations);
...@@ -1309,10 +1319,16 @@ Future<ReassembleResult> _defaultReassembleHelper( ...@@ -1309,10 +1319,16 @@ Future<ReassembleResult> _defaultReassembleHelper(
isolateId: view.uiIsolate!.id!, isolateId: view.uiIsolate!.id!,
); );
} }
reassembleFutures.add(reassembleWork.catchError((dynamic error) { reassembleFutures.add(reassembleWork.then(
failedReassemble = true; (Object? obj) => obj,
globals.printError('Reassembling ${view.uiIsolate!.name} failed: $error'); onError: (Object error, StackTrace stackTrace) {
}, test: (dynamic error) => error is Exception)); if (error is! Exception) {
return Future<Object?>.error(error, stackTrace);
}
failedReassemble = true;
globals.printError('Reassembling ${view.uiIsolate!.name} failed: $error\n$stackTrace');
},
));
} }
} }
} }
......
...@@ -129,11 +129,16 @@ class CoverageCollector extends TestWatcher { ...@@ -129,11 +129,16 @@ class CoverageCollector extends TestWatcher {
final Stopwatch? collectTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageCollect); final Stopwatch? collectTestTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.CoverageCollect);
final Future<void> processComplete = testDevice.finished.catchError( final Future<void> processComplete = testDevice.finished.then(
(Object error) => throw Exception( (Object? obj) => obj,
'Failed to collect coverage, test device terminated prematurely with ' onError: (Object error, StackTrace stackTrace) {
'error: ${(error as TestDeviceException).message}.'), if (error is TestDeviceException) {
test: (Object error) => error is TestDeviceException, throw Exception(
'Failed to collect coverage, test device terminated prematurely with '
'error: ${error.message}.\n$stackTrace');
}
return Future<Object?>.error(error, stackTrace);
}
); );
final Future<void> collectionComplete = testDevice.vmServiceUri final Future<void> collectionComplete = testDevice.vmServiceUri
......
...@@ -680,25 +680,33 @@ class BrowserManager { ...@@ -680,25 +680,33 @@ class BrowserManager {
); );
final Completer<BrowserManager> completer = Completer<BrowserManager>(); final Completer<BrowserManager> completer = Completer<BrowserManager>();
unawaited(chrome.onExit.then<Object?>((int? browserExitCode) { unawaited(chrome.onExit.then<Object?>(
throwToolExit('${runtime.name} exited with code $browserExitCode before connecting.'); (int? browserExitCode) {
}).catchError((Object error, StackTrace stackTrace) { throwToolExit('${runtime.name} exited with code $browserExitCode before connecting.');
if (!completer.isCompleted) { },
completer.completeError(error, stackTrace); ).then(
} (Object? obj) => obj,
return null; onError: (Object error, StackTrace stackTrace) {
})); if (!completer.isCompleted) {
unawaited(future.then((WebSocketChannel webSocket) { completer.completeError(error, stackTrace);
if (completer.isCompleted) { }
return; return null;
} },
completer.complete(BrowserManager._(chrome, runtime, webSocket)); ));
}).catchError((Object error, StackTrace stackTrace) { unawaited(future.then(
chrome.close(); (WebSocketChannel webSocket) {
if (!completer.isCompleted) { if (completer.isCompleted) {
completer.completeError(error, stackTrace); return;
} }
})); completer.complete(BrowserManager._(chrome, runtime, webSocket));
},
onError: (Object error, StackTrace stackTrace) {
chrome.close();
if (!completer.isCompleted) {
completer.completeError(error, stackTrace);
}
},
));
return completer.future; return completer.future;
} }
......
...@@ -287,10 +287,17 @@ Future<vm_service.VmService> setUpVmService( ...@@ -287,10 +287,17 @@ Future<vm_service.VmService> setUpVmService(
vmService.onExtensionEvent.listen(printStructuredErrorLogMethod); vmService.onExtensionEvent.listen(printStructuredErrorLogMethod);
registrationRequests.add(vmService registrationRequests.add(vmService
.streamListen(vm_service.EventStreams.kExtension) .streamListen(vm_service.EventStreams.kExtension)
.then<vm_service.Success?>((vm_service.Success success) => success) .then<vm_service.Success?>(
// It is safe to ignore this error because we expect an error to be (vm_service.Success success) => success,
// thrown if we're already subscribed. // It is safe to ignore this error because we expect an error to be
.catchError((Object? error) => null, test: (Object? error) => error is vm_service.RPCError) // thrown if we're already subscribed.
onError: (Object error, StackTrace stackTrace) {
if (error is vm_service.RPCError) {
return null;
}
return Future<vm_service.Success?>.error(error, stackTrace);
},
),
); );
} }
...@@ -971,14 +978,16 @@ class FlutterVmService { ...@@ -971,14 +978,16 @@ class FlutterVmService {
/// been collected. /// been collected.
Future<vm_service.Isolate?> getIsolateOrNull(String isolateId) async { Future<vm_service.Isolate?> getIsolateOrNull(String isolateId) async {
return service.getIsolate(isolateId) return service.getIsolate(isolateId)
// The .then() call is required to cast from Future<Isolate> to Future<Isolate?> .then<vm_service.Isolate?>(
.then<vm_service.Isolate?>((vm_service.Isolate isolate) => isolate) (vm_service.Isolate isolate) => isolate,
.catchError((Object? error, StackTrace stackTrace) { onError: (Object? error, StackTrace stackTrace) {
return null; if (error is vm_service.SentinelException ||
}, test: (Object? error) { error == null ||
return (error is vm_service.SentinelException) || (error is vm_service.RPCError && error.code == RPCErrorCodes.kServiceDisappeared)) {
(error is vm_service.RPCError && error.code == RPCErrorCodes.kServiceDisappeared); return null;
}); }
return Future<vm_service.Isolate?>.error(error, stackTrace);
});
} }
/// Create a new development file system on the device. /// Create a new development file system on the device.
......
...@@ -164,9 +164,12 @@ void main() { ...@@ -164,9 +164,12 @@ void main() {
await FakeAsync().run((FakeAsync time) { await FakeAsync().run((FakeAsync time) {
unawaited(runZonedGuarded(() async { unawaited(runZonedGuarded(() async {
final Future<void> f = asyncGuard<void>(() => delayedThrow(time)) final Future<void> f = asyncGuard<void>(() => delayedThrow(time))
.catchError((Object e, StackTrace s) { .then(
caughtByCatchError = true; (Object? obj) => obj,
}); onError: (Object e, StackTrace s) {
caughtByCatchError = true;
},
);
try { try {
await f; await f;
} on _CustomException { } on _CustomException {
......
...@@ -54,8 +54,8 @@ void main() { ...@@ -54,8 +54,8 @@ void main() {
final Set<int> completed = <int>{}; final Set<int> completed = <int>{};
final TaskQueue<void> tracker = TaskQueue<void>(maxJobs: 1); final TaskQueue<void> tracker = TaskQueue<void>(maxJobs: 1);
await tracker.add(() async => completed.add(0)); await tracker.add(() async => completed.add(0));
await tracker.add(() async => throw TestException()).catchError((Object _) {}); await tracker.add(() async => throw TestException()).then((_) {}, onError: (Object _) {});
await tracker.add(() async => throw TestException()).catchError((Object _) {}); await tracker.add(() async => throw TestException()).then((_) {}, onError: (Object _) {});
await tracker.add(() async => completed.add(3)); await tracker.add(() async => completed.add(3));
await tracker.tasksComplete; await tracker.tasksComplete;
expect(completed.length, equals(2)); expect(completed.length, equals(2));
......
...@@ -27,7 +27,10 @@ class DapTestClient { ...@@ -27,7 +27,10 @@ class DapTestClient {
vmServiceUri = event('dart.debuggerUris').then<Uri?>((Event event) { vmServiceUri = event('dart.debuggerUris').then<Uri?>((Event event) {
final Map<String, Object?> body = event.body! as Map<String, Object?>; final Map<String, Object?> body = event.body! as Map<String, Object?>;
return Uri.parse(body['vmServiceUri']! as String); return Uri.parse(body['vmServiceUri']! as String);
}).catchError((Object? e) => null); }).then(
(Uri? uri) => uri,
onError: (Object? e) => null,
);
_subscription = _channel.listen( _subscription = _channel.listen(
_handleMessage, _handleMessage,
......
...@@ -298,10 +298,13 @@ Future<ProcessTestResult> runFlutter( ...@@ -298,10 +298,13 @@ Future<ProcessTestResult> runFlutter(
} }
process.stdin.write('q'); process.stdin.write('q');
return -1; // discarded return -1; // discarded
}).catchError((Object error) { }).then(
// ignore errors here, they will be reported on the next line (int i) => i,
return -1; // discarded onError: (Object error) {
})); // ignore errors here, they will be reported on the next line
return -1; // discarded
},
));
final int exitCode = await process.exitCode; final int exitCode = await process.exitCode;
if (streamingLogs) { if (streamingLogs) {
debugPrint('${stamp()} (process terminated with exit code $exitCode)'); debugPrint('${stamp()} (process terminated with exit code $exitCode)');
......
...@@ -194,10 +194,13 @@ abstract class FlutterTestDriver { ...@@ -194,10 +194,13 @@ abstract class FlutterTestDriver {
// it forcefully and it won't terminate child processes, so we need to ensure // it forcefully and it won't terminate child processes, so we need to ensure
// it's running before terminating. // it's running before terminating.
await resume().timeout(defaultTimeout) await resume().timeout(defaultTimeout)
.catchError((Object e) { .then(
_debugPrint('Ignoring failure to resume during shutdown'); (Isolate? isolate) => isolate,
return null; onError: (Object e) {
}); _debugPrint('Ignoring failure to resume during shutdown');
return null;
},
);
_debugPrint('Sending SIGTERM to $_processPid..'); _debugPrint('Sending SIGTERM to $_processPid..');
io.Process.killPid(_processPid!); io.Process.killPid(_processPid!);
...@@ -472,13 +475,16 @@ abstract class FlutterTestDriver { ...@@ -472,13 +475,16 @@ abstract class FlutterTestDriver {
}); });
final Future<T> future = callback().whenComplete(longWarning.cancel); final Future<T> future = callback().whenComplete(longWarning.cancel);
return future.catchError((Object error) { return future.then(
if (!timeoutExpired) { (T t) => t,
timeoutExpired = true; onError: (Object error) {
_debugPrint(messages.toString()); if (!timeoutExpired) {
} timeoutExpired = true;
throw error; // ignore: only_throw_errors _debugPrint(messages.toString());
}).whenComplete(() => subscription.cancel()); }
throw error; // ignore: only_throw_errors
},
).whenComplete(() => subscription.cancel());
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment