Unverified Commit 72ff553a authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] migrate io, process, logger, terminal (#78816)

parent 5a21e2d8
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// This file serves as the single point of entry into the `dart:io` APIs
/// within Flutter tools.
///
......@@ -140,7 +138,7 @@ bool _inUnitTest() {
/// Sets the [exit] function to a function that throws an exception rather
/// than exiting the process; this is intended for testing purposes.
@visibleForTesting
void setExitFunctionForTests([ ExitFunction exitFunction ]) {
void setExitFunctionForTests([ ExitFunction? exitFunction ]) {
_exitFunction = exitFunction ?? (int exitCode) {
throw ProcessExit(exitCode, immediate: true);
};
......@@ -235,12 +233,12 @@ class Stdio {
/// dart:io.
@visibleForTesting
Stdio.test({
@required io.Stdout stdout,
@required io.IOSink stderr,
required io.Stdout stdout,
required io.IOSink stderr,
}) : _stdoutOverride = stdout, _stderrOverride = stderr;
io.Stdout _stdoutOverride;
io.IOSink _stderrOverride;
io.Stdout? _stdoutOverride;
io.IOSink? _stderrOverride;
// These flags exist to remember when the done Futures on stdout and stderr
// complete to avoid trying to write to a closed stream sink, which would
......@@ -253,34 +251,34 @@ class Stdio {
@visibleForTesting
io.Stdout get stdout {
if (_stdout != null) {
return _stdout;
return _stdout!;
}
_stdout = _stdoutOverride ?? io.stdout;
_stdout.done.then(
_stdout!.done.then(
(void _) { _stdoutDone = true; },
onError: (Object err, StackTrace st) { _stdoutDone = true; },
);
return _stdout;
return _stdout!;
}
io.Stdout _stdout;
io.Stdout? _stdout;
@visibleForTesting
io.IOSink get stderr {
if (_stderr != null) {
return _stderr;
return _stderr!;
}
_stderr = _stderrOverride ?? io.stderr;
_stderr.done.then(
_stderr!.done.then(
(void _) { _stderrDone = true; },
onError: (Object err, StackTrace st) { _stderrDone = true; },
);
return _stderr;
return _stderr!;
}
io.IOSink _stderr;
io.IOSink? _stderr;
bool get hasTerminal => io.stdout.hasTerminal;
static bool _stdinHasTerminal;
static bool? _stdinHasTerminal;
/// Determines whether there is a terminal attached.
///
......@@ -290,7 +288,7 @@ class Stdio {
/// runtime errors such as "inappropriate ioctl for device" if not handled.
bool get stdinHasTerminal {
if (_stdinHasTerminal != null) {
return _stdinHasTerminal;
return _stdinHasTerminal!;
}
if (stdin is! io.Stdin) {
return _stdinHasTerminal = false;
......@@ -309,15 +307,15 @@ class Stdio {
return _stdinHasTerminal = true;
}
int get terminalColumns => hasTerminal ? stdout.terminalColumns : null;
int get terminalLines => hasTerminal ? stdout.terminalLines : null;
int? get terminalColumns => hasTerminal ? stdout.terminalColumns : null;
int? get terminalLines => hasTerminal ? stdout.terminalLines : null;
bool get supportsAnsiEscapes => hasTerminal && stdout.supportsAnsiEscapes;
/// Writes [message] to [stderr], falling back on [fallback] if the write
/// throws any exception. The default fallback calls [print] on [message].
void stderrWrite(
String message, {
void Function(String, dynamic, StackTrace) fallback,
void Function(String, dynamic, StackTrace)? fallback,
}) {
if (!_stderrDone) {
_stdioWrite(stderr, message, fallback: fallback);
......@@ -334,7 +332,7 @@ class Stdio {
/// throws any exception. The default fallback calls [print] on [message].
void stdoutWrite(
String message, {
void Function(String, dynamic, StackTrace) fallback,
void Function(String, dynamic, StackTrace)? fallback,
}) {
if (!_stdoutDone) {
_stdioWrite(stdout, message, fallback: fallback);
......@@ -349,7 +347,7 @@ class Stdio {
// Helper for [stderrWrite] and [stdoutWrite].
void _stdioWrite(io.IOSink sink, String message, {
void Function(String, dynamic, StackTrace) fallback,
void Function(String, dynamic, StackTrace)? fallback,
}) {
asyncGuard<void>(() async {
sink.write(message);
......@@ -447,7 +445,7 @@ typedef NetworkInterfaceLister = Future<List<NetworkInterface>> Function({
io.InternetAddressType type,
});
NetworkInterfaceLister _networkInterfaceListerOverride;
NetworkInterfaceLister? _networkInterfaceListerOverride;
// Tests can set up a non-default network interface lister.
@visibleForTesting
......@@ -469,7 +467,7 @@ Future<List<NetworkInterface>> listNetworkInterfaces({
io.InternetAddressType type = io.InternetAddressType.any,
}) async {
if (_networkInterfaceListerOverride != null) {
return _networkInterfaceListerOverride(
return _networkInterfaceListerOverride!.call(
includeLoopback: includeLoopback,
includeLinkLocal: includeLinkLocal,
type: type,
......
......@@ -2,11 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../convert.dart';
......@@ -27,7 +24,7 @@ typedef ShutdownHook = FutureOr<dynamic> Function();
abstract class ShutdownHooks {
factory ShutdownHooks({
@required Logger logger,
required Logger logger,
}) => _DefaultShutdownHooks(
logger: logger,
);
......@@ -49,7 +46,7 @@ abstract class ShutdownHooks {
class _DefaultShutdownHooks implements ShutdownHooks {
_DefaultShutdownHooks({
@required Logger logger,
required Logger logger,
}) : _logger = logger;
final Logger _logger;
......@@ -137,8 +134,8 @@ typedef RunResultChecker = bool Function(int);
abstract class ProcessUtils {
factory ProcessUtils({
@required ProcessManager processManager,
@required Logger logger,
required ProcessManager processManager,
required Logger logger,
}) => _DefaultProcessUtils(
processManager: processManager,
logger: logger,
......@@ -236,8 +233,8 @@ abstract class ProcessUtils {
class _DefaultProcessUtils implements ProcessUtils {
_DefaultProcessUtils({
@required ProcessManager processManager,
@required Logger logger,
required ProcessManager processManager,
required Logger logger,
}) : _processManager = processManager,
_logger = logger;
......@@ -249,11 +246,11 @@ class _DefaultProcessUtils implements ProcessUtils {
Future<RunResult> run(
List<String> cmd, {
bool throwOnError = false,
RunResultChecker allowedFailures,
String workingDirectory,
RunResultChecker? allowedFailures,
String? workingDirectory,
bool allowReentrantFlutter = false,
Map<String, String> environment,
Duration timeout,
Map<String, String>? environment,
Duration? timeout,
int timeoutRetries = 0,
}) async {
if (cmd == null || cmd.isEmpty) {
......@@ -305,8 +302,8 @@ class _DefaultProcessUtils implements ProcessUtils {
.listen(stderrBuffer.write)
.asFuture<void>(null);
int exitCode;
exitCode = await process.exitCode.timeout(timeout, onTimeout: () {
int? exitCode;
exitCode = await process.exitCode.then<int?>((int x) => x).timeout(timeout, onTimeout: () {
// The process timed out. Kill it.
_processManager.killPid(process.pid);
return null;
......@@ -324,7 +321,7 @@ class _DefaultProcessUtils implements ProcessUtils {
stdioFuture = stdioFuture.timeout(const Duration(seconds: 1));
}
await stdioFuture;
} on Exception catch (_) {
} on Exception {
// Ignore errors on the process' stdout and stderr streams. Just capture
// whatever we got, and use the exit code
}
......@@ -365,10 +362,10 @@ class _DefaultProcessUtils implements ProcessUtils {
List<String> cmd, {
bool throwOnError = false,
bool verboseExceptions = false,
RunResultChecker allowedFailures,
RunResultChecker? allowedFailures,
bool hideStdout = false,
String workingDirectory,
Map<String, String> environment,
String? workingDirectory,
Map<String, String>? environment,
bool allowReentrantFlutter = false,
Encoding encoding = systemEncoding,
}) {
......@@ -420,9 +417,9 @@ class _DefaultProcessUtils implements ProcessUtils {
@override
Future<Process> start(
List<String> cmd, {
String workingDirectory,
String? workingDirectory,
bool allowReentrantFlutter = false,
Map<String, String> environment,
Map<String, String>? environment,
}) {
_traceCommand(cmd, workingDirectory: workingDirectory);
return _processManager.start(
......@@ -435,14 +432,14 @@ class _DefaultProcessUtils implements ProcessUtils {
@override
Future<int> stream(
List<String> cmd, {
String workingDirectory,
String? workingDirectory,
bool allowReentrantFlutter = false,
String prefix = '',
bool trace = false,
RegExp filter,
RegExp stdoutErrorMatcher,
StringConverter mapFunction,
Map<String, String> environment,
RegExp? filter,
RegExp? stdoutErrorMatcher,
StringConverter? mapFunction,
Map<String, String>? environment,
}) async {
final Process process = await start(
cmd,
......@@ -503,7 +500,7 @@ class _DefaultProcessUtils implements ProcessUtils {
@override
bool exitsHappySync(
List<String> cli, {
Map<String, String> environment,
Map<String, String>? environment,
}) {
_traceCommand(cli);
if (!_processManager.canRun(cli.first)) {
......@@ -522,7 +519,7 @@ class _DefaultProcessUtils implements ProcessUtils {
@override
Future<bool> exitsHappy(
List<String> cli, {
Map<String, String> environment,
Map<String, String>? environment,
}) async {
_traceCommand(cli);
if (!_processManager.canRun(cli.first)) {
......@@ -538,8 +535,8 @@ class _DefaultProcessUtils implements ProcessUtils {
}
}
Map<String, String> _environment(bool allowReentrantFlutter, [
Map<String, String> environment,
Map<String, String>? _environment(bool allowReentrantFlutter, [
Map<String, String>? environment,
]) {
if (allowReentrantFlutter) {
if (environment == null) {
......@@ -552,7 +549,7 @@ class _DefaultProcessUtils implements ProcessUtils {
return environment;
}
void _traceCommand(List<String> args, { String workingDirectory }) {
void _traceCommand(List<String> args, { String? workingDirectory }) {
final String argsText = args.join(' ');
if (workingDirectory == null) {
_logger.printTrace('executing: $argsText');
......
......@@ -2,10 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import '../convert.dart';
import 'io.dart' as io;
import 'logger.dart';
......@@ -25,12 +21,12 @@ enum TerminalColor {
/// console.
class OutputPreferences {
OutputPreferences({
bool wrapText,
int wrapColumn,
bool showColor,
io.Stdio stdio,
bool? wrapText,
int? wrapColumn,
bool? showColor,
io.Stdio? stdio,
}) : _stdio = stdio,
wrapText = wrapText ?? stdio.hasTerminal,
wrapText = wrapText ?? stdio?.hasTerminal ?? false,
_overrideWrapColumn = wrapColumn,
showColor = showColor ?? false;
......@@ -38,7 +34,7 @@ class OutputPreferences {
OutputPreferences.test({this.wrapText = false, int wrapColumn = kDefaultTerminalColumns, this.showColor = false})
: _overrideWrapColumn = wrapColumn, _stdio = null;
final io.Stdio _stdio;
final io.Stdio? _stdio;
/// If [wrapText] is true, then any text sent to the context's [Logger]
/// instance (e.g. from the [printError] or [printStatus] functions) will be
......@@ -56,7 +52,7 @@ class OutputPreferences {
/// (e.g. from the [printError] or [printStatus] functions) will be wrapped.
/// Ignored if [wrapText] is false. Defaults to the width of the output
/// terminal, or to [kDefaultTerminalColumns] if not writing to a terminal.
final int _overrideWrapColumn;
final int? _overrideWrapColumn;
int get wrapColumn {
return _overrideWrapColumn ?? _stdio?.terminalColumns ?? kDefaultTerminalColumns;
}
......@@ -136,17 +132,17 @@ abstract class Terminal {
/// If [usesTerminalUi] is false, throws a [StateError].
Future<String> promptForCharInput(
List<String> acceptedCharacters, {
@required Logger logger,
String prompt,
int defaultChoiceIndex,
required Logger logger,
String? prompt,
int? defaultChoiceIndex,
bool displayAcceptedCharacters = true,
});
}
class AnsiTerminal implements Terminal {
AnsiTerminal({
@required io.Stdio stdio,
@required Platform platform,
required io.Stdio stdio,
required Platform platform,
})
: _stdio = stdio,
_platform = platform;
......@@ -178,10 +174,10 @@ class AnsiTerminal implements Terminal {
TerminalColor.grey: grey,
};
static String colorCode(TerminalColor color) => _colorMap[color];
static String colorCode(TerminalColor color) => _colorMap[color]!;
@override
bool get supportsColor => _platform?.stdoutSupportsAnsi ?? false;
bool get supportsColor => _platform.stdoutSupportsAnsi;
// Assume unicode emojis are supported when not on Windows.
// If we are on Windows, unicode emojis are supported in Windows Terminal,
......@@ -236,7 +232,7 @@ class AnsiTerminal implements Terminal {
return message;
}
final StringBuffer buffer = StringBuffer();
final String colorCodes = _colorMap[color];
final String colorCodes = _colorMap[color]!;
for (String line in message.split('\n')) {
// If there were resets in the string before, then keep them, but
// restart the color right after. This prevents embedded resets from
......@@ -273,26 +269,23 @@ class AnsiTerminal implements Terminal {
@override
bool get stdinHasTerminal => _stdio.stdinHasTerminal;
Stream<String> _broadcastStdInString;
Stream<String>? _broadcastStdInString;
@override
Stream<String> get keystrokes {
_broadcastStdInString ??= _stdio.stdin.transform<String>(const AsciiDecoder(allowInvalid: true)).asBroadcastStream();
return _broadcastStdInString;
return _broadcastStdInString ??= _stdio.stdin.transform<String>(const AsciiDecoder(allowInvalid: true)).asBroadcastStream();
}
@override
Future<String> promptForCharInput(
List<String> acceptedCharacters, {
@required Logger logger,
String prompt,
int defaultChoiceIndex,
required Logger logger,
String? prompt,
int? defaultChoiceIndex,
bool displayAcceptedCharacters = true,
}) async {
assert(acceptedCharacters != null);
assert(acceptedCharacters.isNotEmpty);
assert(prompt == null || prompt.isNotEmpty);
assert(displayAcceptedCharacters != null);
if (!usesTerminalUi) {
throw StateError('cannot prompt without a terminal ui');
}
......@@ -303,7 +296,7 @@ class AnsiTerminal implements Terminal {
charactersToDisplay[defaultChoiceIndex] = bolden(charactersToDisplay[defaultChoiceIndex]);
acceptedCharacters.add('');
}
String choice;
String? choice;
singleCharMode = true;
while (choice == null || choice.length > 1 || !acceptedCharacters.contains(choice)) {
if (prompt != null) {
......@@ -329,7 +322,7 @@ class _TestTerminal implements Terminal {
_TestTerminal({this.supportsColor = false, this.supportsEmoji = false});
@override
bool usesTerminalUi;
bool usesTerminalUi = false;
@override
String bolden(String message) => message;
......@@ -345,9 +338,9 @@ class _TestTerminal implements Terminal {
@override
Future<String> promptForCharInput(List<String> acceptedCharacters, {
@required Logger logger,
String prompt,
int defaultChoiceIndex,
required Logger logger,
String? prompt,
int? defaultChoiceIndex,
bool displayAcceptedCharacters = true,
}) {
throw UnsupportedError('promptForCharInput not supported in the test terminal.');
......
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