From 045ba2b66171c5c47b9aa349b4221b5984bc5a89 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Mon, 19 Jul 2021 13:59:15 -0700 Subject: [PATCH] Migrate dev/bots to null safety (#86522) --- dev/bots/analyze.dart | 69 +++++----- dev/bots/browser.dart | 21 ++- dev/bots/flutter_compact_formatter.dart | 34 +++-- dev/bots/prepare_package.dart | 48 ++++--- dev/bots/pubspec.yaml | 2 +- dev/bots/run_command.dart | 47 +++---- dev/bots/service_worker_test.dart | 29 ++--- dev/bots/test.dart | 122 +++++++++--------- dev/bots/test/prepare_package_test.dart | 36 +++--- .../test/sdk_directory_has_space_test.dart | 4 +- dev/bots/test/test_test.dart | 4 +- dev/bots/unpublish_package.dart | 38 +++--- 12 files changed, 216 insertions(+), 238 deletions(-) diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index dc98d756ab..e24c1fd573 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -167,17 +167,17 @@ Future verifyDeprecations(String workingDirectory, { int minimumMatches = } for (int lineNumber in linesWithDeprecations) { try { - final Match match1 = _deprecationPattern1.firstMatch(lines[lineNumber]); + final Match? match1 = _deprecationPattern1.firstMatch(lines[lineNumber]); if (match1 == null) throw 'Deprecation notice does not match required pattern.'; - final String indent = match1[1]; + final String indent = match1[1]!; lineNumber += 1; if (lineNumber >= lines.length) throw 'Incomplete deprecation notice.'; - Match match3; - String message; + Match? match3; + String? message; do { - final Match match2 = _deprecationPattern2.firstMatch(lines[lineNumber]); + final Match? match2 = _deprecationPattern2.firstMatch(lines[lineNumber]); if (match2 == null) { String possibleReason = ''; if (lines[lineNumber].trimLeft().startsWith('"')) { @@ -188,7 +188,7 @@ Future verifyDeprecations(String workingDirectory, { int minimumMatches = if (!lines[lineNumber].startsWith("$indent '")) throw 'Unexpected deprecation notice indent.'; if (message == null) { - final String firstChar = String.fromCharCode(match2[1].runes.first); + final String firstChar = String.fromCharCode(match2[1]!.runes.first); if (firstChar.toUpperCase() != firstChar) throw 'Deprecation notice should be a grammatically correct sentence and start with a capital letter; see style guide: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo'; } @@ -198,14 +198,14 @@ Future verifyDeprecations(String workingDirectory, { int minimumMatches = throw 'Incomplete deprecation notice.'; match3 = _deprecationPattern3.firstMatch(lines[lineNumber]); } while (match3 == null); - final int v1 = int.parse(match3[1]); - final int v2 = int.parse(match3[2]); + final int v1 = int.parse(match3[1]!); + final int v2 = int.parse(match3[2]!); final bool hasV4 = match3[4] != null; if (v1 > 1 || (v1 == 1 && v2 >= 20)) { if (!hasV4) throw 'Deprecation notice does not accurately indicate a dev branch version number; please see https://flutter.dev/docs/development/tools/sdk/releases to find the latest dev build version number.'; } - if (!message.endsWith('.') && !message.endsWith('!') && !message.endsWith('?')) + if (!message!.endsWith('.') && !message.endsWith('!') && !message.endsWith('?')) throw 'Deprecation notice should be a grammatically correct sentence and end with a period.'; if (!lines[lineNumber].startsWith("$indent '")) throw 'Unexpected deprecation notice indent.'; @@ -238,7 +238,7 @@ String _generateLicense(String prefix) { } Future verifyNoMissingLicense(String workingDirectory, { bool checkMinimums = true }) async { - final int overrideMinimumMatches = checkMinimums ? null : 0; + final int? overrideMinimumMatches = checkMinimums ? null : 0; await _verifyNoMissingLicenseForExtension(workingDirectory, 'dart', overrideMinimumMatches ?? 2000, _generateLicense('// ')); await _verifyNoMissingLicenseForExtension(workingDirectory, 'java', overrideMinimumMatches ?? 39, _generateLicense('// ')); await _verifyNoMissingLicenseForExtension(workingDirectory, 'h', overrideMinimumMatches ?? 30, _generateLicense('// ')); @@ -291,7 +291,7 @@ Future verifyNoTestImports(String workingDirectory) async { final List dartFiles = await _allFiles(path.join(workingDirectory, 'packages'), 'dart', minimumMatches: 1500).toList(); for (final File file in dartFiles) { for (final String line in file.readAsLinesSync()) { - final Match match = _testImportPattern.firstMatch(line); + final Match? match = _testImportPattern.firstMatch(line); if (match != null && !_exemptTestImports.contains(match.group(2))) errors.add(file.path); } @@ -333,11 +333,11 @@ Future verifyNoBadImportsInFlutter(String workingDirectory) async { for (final String directory in directories) { dependencyMap[directory] = await _findFlutterDependencies(path.join(srcPath, directory), errors, checkForMeta: directory != 'foundation'); } - assert(dependencyMap['material'].contains('widgets') && - dependencyMap['widgets'].contains('rendering') && - dependencyMap['rendering'].contains('painting')); // to make sure we're convinced _findFlutterDependencies is finding some + assert(dependencyMap['material']!.contains('widgets') && + dependencyMap['widgets']!.contains('rendering') && + dependencyMap['rendering']!.contains('painting')); // to make sure we're convinced _findFlutterDependencies is finding some for (final String package in dependencyMap.keys) { - if (dependencyMap[package].contains(package)) { + if (dependencyMap[package]!.contains(package)) { errors.add( 'One of the files in the $yellow$package$reset package imports that package recursively.' ); @@ -345,7 +345,7 @@ Future verifyNoBadImportsInFlutter(String workingDirectory) async { } for (final String key in dependencyMap.keys) { - for (final String dependency in dependencyMap[key]) { + for (final String dependency in dependencyMap[key]!) { if (dependencyMap[dependency] != null) continue; // Sanity check before performing _deepSearch, to ensure there's no rogue @@ -360,7 +360,7 @@ Future verifyNoBadImportsInFlutter(String workingDirectory) async { } for (final String package in dependencyMap.keys) { - final List loop = _deepSearch(dependencyMap, package); + final List? loop = _deepSearch(dependencyMap, package); if (loop != null) { errors.add('${yellow}Dependency loop:$reset ${loop.join(' depends on ')}'); } @@ -973,7 +973,7 @@ final Set _legacyBinaries = { const Hash256(0x63D2ABD0041C3E3B, 0x4B52AD8D382353B5, 0x3C51C6785E76CE56, 0xED9DACAD2D2E31C4), }; -Future verifyNoBinaries(String workingDirectory, { Set legacyBinaries }) async { +Future verifyNoBinaries(String workingDirectory, { Set? legacyBinaries }) async { // Please do not add anything to the _legacyBinaries set above. // We have a policy of not checking in binaries into this repository. // If you are adding/changing template images, use the flutter_template_images @@ -1051,7 +1051,7 @@ Future> _gitFiles(String workingDirectory, {bool runSilently = true}) .toList(); } -Stream _allFiles(String workingDirectory, String extension, { @required int minimumMatches }) async* { +Stream _allFiles(String workingDirectory, String? extension, { required int minimumMatches }) async* { final Set gitFileNamesSet = {}; gitFileNamesSet.addAll((await _gitFiles(workingDirectory)).map((File f) => path.canonicalize(f.absolute.path))); @@ -1101,8 +1101,8 @@ Stream _allFiles(String workingDirectory, String extension, { @required in class EvalResult { EvalResult({ - this.stdout, - this.stderr, + required this.stdout, + required this.stderr, this.exitCode = 0, }); @@ -1113,18 +1113,13 @@ class EvalResult { // TODO(ianh): Refactor this to reuse the code in run_command.dart Future _evalCommand(String executable, List arguments, { - @required String workingDirectory, - Map environment, - bool skip = false, + required String workingDirectory, + Map? environment, bool allowNonZeroExit = false, bool runSilently = false, }) async { final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}'; final String relativeWorkingDir = path.relative(workingDirectory); - if (skip) { - printProgress('SKIPPING', relativeWorkingDir, commandDescription); - return null; - } if (!runSilently) { printProgress('RUNNING', relativeWorkingDir, commandDescription); @@ -1168,8 +1163,8 @@ Future _checkConsumerDependencies() async { '--consumer-only', ]); if (result.exitCode != 0) { - print(result.stdout); - print(result.stderr); + print(result.stdout as Object); + print(result.stderr as Object); exit(result.exitCode); } final Set dependencySet = {}; @@ -1217,7 +1212,7 @@ Future _checkConsumerDependencies() async { } } -Future _runFlutterAnalyze(String workingDirectory, { +Future _runFlutterAnalyze(String workingDirectory, { List options = const [], }) async { return runCommand( @@ -1235,9 +1230,9 @@ Future> _findFlutterDependencies(String srcPath, List errors .map>((File file) { final Set result = {}; for (final String line in file.readAsLinesSync()) { - Match match = _importPattern.firstMatch(line); + Match? match = _importPattern.firstMatch(line); if (match != null) - result.add(match.group(2)); + result.add(match.group(2)!); if (checkForMeta) { match = _importMetaPattern.firstMatch(line); if (match != null) { @@ -1250,23 +1245,23 @@ Future> _findFlutterDependencies(String srcPath, List errors } return result; }) - .reduce((Set value, Set element) { + .reduce((Set? value, Set element) { value ??= {}; value.addAll(element); return value; }); } -List _deepSearch(Map> map, T start, [ Set seen ]) { +List? _deepSearch(Map> map, T start, [ Set? seen ]) { if (map[start] == null) return null; // We catch these separately. - for (final T key in map[start]) { + for (final T key in map[start]!) { if (key == start) continue; // we catch these separately if (seen != null && seen.contains(key)) return [start, key]; - final List result = _deepSearch( + final List? result = _deepSearch( map, key, { diff --git a/dev/bots/browser.dart b/dev/bots/browser.dart index 0b0651e2b3..e0303dbe13 100644 --- a/dev/bots/browser.dart +++ b/dev/bots/browser.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:io' as io; import 'package:flutter_devicelab/framework/browser.dart'; -import 'package:meta/meta.dart'; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:shelf_static/shelf_static.dart'; @@ -21,13 +20,13 @@ import 'package:shelf_static/shelf_static.dart'; /// request to "/test-result" containing result data as plain text body of the /// request. This function has no opinion about what that string contains. Future evalTestAppInChrome({ - @required String appUrl, - @required String appDirectory, + required String appUrl, + required String appDirectory, int serverPort = 8080, int browserDebugPort = 8081, }) async { - io.HttpServer server; - Chrome chrome; + io.HttpServer? server; + Chrome? chrome; try { final Completer resultCompleter = Completer(); server = await io.HttpServer.bind('localhost', serverPort); @@ -63,13 +62,13 @@ class AppServer { AppServer._(this._server, this.chrome, this.onChromeError); static Future start({ - @required String appUrl, - @required String appDirectory, - @required String cacheControl, + required String appUrl, + required String appDirectory, + required String cacheControl, int serverPort = 8080, int browserDebugPort = 8081, bool headless = true, - List additionalRequestHandlers, + List? additionalRequestHandlers, }) async { io.HttpServer server; Chrome chrome; @@ -106,7 +105,7 @@ class AppServer { final Chrome chrome; Future stop() async { - chrome?.stop(); - await _server?.close(); + chrome.stop(); + await _server.close(); } } diff --git a/dev/bots/flutter_compact_formatter.dart b/dev/bots/flutter_compact_formatter.dart index 0b5552c1ee..9bb08fd0c0 100644 --- a/dev/bots/flutter_compact_formatter.dart +++ b/dev/bots/flutter_compact_formatter.dart @@ -5,8 +5,6 @@ import 'dart:convert'; import 'dart:io'; -import 'package:meta/meta.dart'; - final Stopwatch _stopwatch = Stopwatch(); /// A wrapper around package:test's JSON reporter. @@ -75,7 +73,7 @@ class FlutterCompactFormatter { /// /// Callers are responsible for splitting multiple lines before calling this /// method. - TestResult processRawOutput(String raw) { + TestResult? processRawOutput(String raw) { assert(raw != null); // We might be getting messages from Flutter Tool about updating/building. if (!raw.startsWith('{')) { @@ -83,7 +81,7 @@ class FlutterCompactFormatter { return null; } final Map decoded = json.decode(raw) as Map; - final TestResult originalResult = _tests[decoded['testID']]; + final TestResult? originalResult = _tests[decoded['testID']]; switch (decoded['type'] as String) { case 'done': stdout.write(_clearLine); @@ -104,9 +102,9 @@ class FlutterCompactFormatter { _tests[testData['id'] as int] = TestResult( id: testData['id'] as int, name: testData['name'] as String, - line: testData['root_line'] as int ?? testData['line'] as int, - column: testData['root_column'] as int ?? testData['column'] as int, - path: testData['root_url'] as String ?? testData['url'] as String, + line: testData['root_line'] as int? ?? testData['line'] as int, + column: testData['root_column'] as int? ?? testData['column'] as int, + path: testData['root_url'] as String? ?? testData['url'] as String, startTime: decoded['time'] as int, ); break; @@ -173,9 +171,9 @@ class FlutterCompactFormatter { case TestStatus.failed: failed.addAll([ '$_bold${_red}Failed ${result.name} (${result.pathLineColumn}):', - result.errorMessage, + result.errorMessage!, _noColor + _red, - result.stackTrace, + result.stackTrace!, ]); failed.addAll(result.messages); failed.add(_noColor); @@ -209,12 +207,12 @@ enum TestStatus { /// The detailed status of a test run. class TestResult { TestResult({ - @required this.id, - @required this.name, - @required this.line, - @required this.column, - @required this.path, - @required this.startTime, + required this.id, + required this.name, + required this.line, + required this.column, + required this.path, + required this.startTime, this.status = TestStatus.started, }) : assert(id != null), assert(name != null), @@ -254,13 +252,13 @@ class TestResult { /// The error message from the test, from an `expect`, an [Exception] or /// [Error]. - String errorMessage; + String? errorMessage; /// The stacktrace from a test failure. - String stackTrace; + String? stackTrace; /// The time, in milliseconds relative to suite startup, that the test ended. - int endTime; + int? endTime; /// The total time, in milliseconds, that the test took. int get totalTime => (endTime ?? _stopwatch.elapsedMilliseconds) - startTime; diff --git a/dev/bots/prepare_package.dart b/dev/bots/prepare_package.dart index 4c88c793f9..e3f3e5c3d4 100644 --- a/dev/bots/prepare_package.dart +++ b/dev/bots/prepare_package.dart @@ -11,7 +11,6 @@ import 'package:args/args.dart'; import 'package:crypto/crypto.dart'; import 'package:crypto/src/digest_sink.dart'; import 'package:http/http.dart' as http; -import 'package:meta/meta.dart' show required; import 'package:path/path.dart' as path; import 'package:platform/platform.dart' show Platform, LocalPlatform; import 'package:process/process.dart'; @@ -32,7 +31,7 @@ class PreparePackageException implements Exception { PreparePackageException(this.message, [this.result]); final String message; - final ProcessResult result; + final ProcessResult? result; int get exitCode => result?.exitCode ?? -1; @override @@ -41,7 +40,7 @@ class PreparePackageException implements Exception { if (message != null) { output += ': $message'; } - final String stderr = result?.stderr as String ?? ''; + final String stderr = result?.stderr as String? ?? ''; if (stderr.isNotEmpty) { output += ':\n$stderr'; } @@ -60,7 +59,6 @@ String getBranchName(Branch branch) { case Branch.stable: return 'stable'; } - return null; } Branch fromBranchName(String name) { @@ -81,7 +79,7 @@ Branch fromBranchName(String name) { /// properly without dropping any. class ProcessRunner { ProcessRunner({ - ProcessManager processManager, + ProcessManager? processManager, this.subprocessOutput = true, this.defaultWorkingDirectory, this.platform = const LocalPlatform(), @@ -102,10 +100,10 @@ class ProcessRunner { /// Sets the default directory used when `workingDirectory` is not specified /// to [runProcess]. - final Directory defaultWorkingDirectory; + final Directory? defaultWorkingDirectory; /// The environment to run processes with. - Map environment; + late Map environment; /// Run the command and arguments in `commandLine` as a sub-process from /// `workingDirectory` if set, or the [defaultWorkingDirectory] if not. Uses @@ -115,7 +113,7 @@ class ProcessRunner { /// command completes with a non-zero exit code. Future runProcess( List commandLine, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { workingDirectory ??= defaultWorkingDirectory ?? Directory.current; @@ -125,7 +123,7 @@ class ProcessRunner { final List output = []; final Completer stdoutComplete = Completer(); final Completer stderrComplete = Completer(); - Process process; + late Process process; Future allComplete() async { await stderrComplete.future; await stdoutComplete.future; @@ -197,10 +195,10 @@ class ArchiveCreator { this.revision, this.branch, { this.strict = true, - ProcessManager processManager, + ProcessManager? processManager, bool subprocessOutput = true, this.platform = const LocalPlatform(), - HttpReader httpReader, + HttpReader? httpReader, }) : assert(revision.length == 40), flutterRoot = Directory(path.join(tempDir.path, 'flutter')), httpReader = httpReader ?? http.readBytes, @@ -252,9 +250,9 @@ class ArchiveCreator { /// [http.readBytes]. final HttpReader httpReader; - File _outputFile; - String _version; - String _flutter; + late File _outputFile; + late String _version; + late String _flutter; /// Get the name of the channel as a string. String get branchName => getBranchName(branch); @@ -446,14 +444,14 @@ class ArchiveCreator { } } - Future _runFlutter(List args, {Directory workingDirectory}) { + Future _runFlutter(List args, {Directory? workingDirectory}) { return _processRunner.runProcess( [_flutter, ...args], workingDirectory: workingDirectory ?? flutterRoot, ); } - Future _runGit(List args, {Directory workingDirectory}) { + Future _runGit(List args, {Directory? workingDirectory}) { return _processRunner.runProcess( ['git', ...args], workingDirectory: workingDirectory ?? flutterRoot, @@ -462,7 +460,7 @@ class ArchiveCreator { /// Unpacks the given zip file into the currentDirectory (if set), or the /// same directory as the archive. - Future _unzipArchive(File archive, {Directory workingDirectory}) { + Future _unzipArchive(File archive, {Directory? workingDirectory}) { workingDirectory ??= Directory(path.dirname(archive.absolute.path)); List commandLine; if (platform.isWindows) { @@ -532,7 +530,7 @@ class ArchivePublisher { this.version, this.outputFile, this.dryRun, { - ProcessManager processManager, + ProcessManager? processManager, bool subprocessOutput = true, this.platform = const LocalPlatform(), }) : assert(revision.length == 40), @@ -662,7 +660,7 @@ class ArchivePublisher { Future _runGsUtil( List args, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { if (dryRun) { @@ -671,7 +669,7 @@ class ArchivePublisher { } if (platform.isWindows) { return _processRunner.runProcess( - ['python', path.join(platform.environment['DEPOT_TOOLS'], 'gsutil.py'), '--', ...args], + ['python', path.join(platform.environment['DEPOT_TOOLS']!, 'gsutil.py'), '--', ...args], workingDirectory: workingDirectory, failOk: failOk, ); @@ -699,14 +697,14 @@ class ArchivePublisher { } Future _cloudCopy({ - @required String src, - @required String dest, - int cacheSeconds, + required String src, + required String dest, + int? cacheSeconds, }) async { // We often don't have permission to overwrite, but // we have permission to remove, so that's what we do. await _runGsUtil(['rm', dest], failOk: true); - String mimeType; + String? mimeType; if (dest.endsWith('.tar.xz')) { mimeType = 'application/x-gtar'; } @@ -841,7 +839,7 @@ Future main(List rawArguments) async { final Branch branch = fromBranchName(parsedArguments['branch'] as String); final ArchiveCreator creator = ArchiveCreator(tempDir, outputDir, revision, branch, strict: parsedArguments['publish'] as bool); int exitCode = 0; - String message; + late String message; try { final String version = await creator.initializeRepo(); final File outputFile = await creator.createArchive(); diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index 9bbd7fd862..2d5579e075 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -2,7 +2,7 @@ name: tests_on_bots description: Scripts which run on bots. environment: - sdk: ">=2.2.2 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: args: 2.1.1 diff --git a/dev/bots/run_command.dart b/dev/bots/run_command.dart index bee2a69be9..13a97f2073 100644 --- a/dev/bots/run_command.dart +++ b/dev/bots/run_command.dart @@ -19,12 +19,12 @@ import 'utils.dart'; /// code fails the test immediately by exiting the test process with exit code /// 1. Stream runAndGetStdout(String executable, List arguments, { - String workingDirectory, - Map environment, + String? workingDirectory, + Map? environment, bool expectNonZeroExit = false, }) async* { final StreamController output = StreamController(); - final Future command = runCommand( + final Future command = runCommand( executable, arguments, workingDirectory: workingDirectory, @@ -52,8 +52,8 @@ class Command { final io.Process process; final Stopwatch _time; - final Future>> _savedStdout; - final Future>> _savedStderr; + final Future>>? _savedStdout; + final Future>>? _savedStderr; /// Evaluates when the [process] exits. /// @@ -63,8 +63,8 @@ class Command { _time.stop(); // Saved output is null when OutputMode.print is used. - final String flattenedStdout = _savedStdout != null ? _flattenToString(await _savedStdout) : null; - final String flattenedStderr = _savedStderr != null ? _flattenToString(await _savedStderr) : null; + final String? flattenedStdout = _savedStdout != null ? _flattenToString((await _savedStdout)!) : null; + final String? flattenedStderr = _savedStderr != null ? _flattenToString((await _savedStderr)!) : null; return CommandResult._(exitCode, _time.elapsed, flattenedStdout, flattenedStderr); } } @@ -80,10 +80,10 @@ class CommandResult { final Duration elapsedTime; /// Standard output decoded as a string using UTF8 decoder. - final String flattenedStdout; + final String? flattenedStdout; /// Standard error output decoded as a string using UTF8 decoder. - final String flattenedStderr; + final String? flattenedStderr; } /// Starts the `executable` and returns a command object representing the @@ -97,11 +97,11 @@ class CommandResult { /// `outputMode` controls where the standard output from the command process /// goes. See [OutputMode]. Future startCommand(String executable, List arguments, { - String workingDirectory, - Map environment, + String? workingDirectory, + Map? environment, OutputMode outputMode = OutputMode.print, - bool Function(String) removeLine, - void Function(String, io.Process) outputListener, + bool Function(String)? removeLine, + void Function(String, io.Process)? outputListener, }) async { final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}'; final String relativeWorkingDir = path.relative(workingDirectory ?? io.Directory.current.path); @@ -113,7 +113,7 @@ Future startCommand(String executable, List arguments, { environment: environment, ); - Future>> savedStdout, savedStderr; + Future>>? savedStdout, savedStderr; final Stream> stdoutSource = process.stdout .transform(const Utf8Decoder()) .transform(const LineSplitter()) @@ -150,27 +150,22 @@ Future startCommand(String executable, List arguments, { /// an indefinitely running process, for example, by waiting until the process /// emits certain output. /// -/// Returns the result of the finished process, or null if `skip` is true. +/// Returns the result of the finished process. /// /// `outputMode` controls where the standard output from the command process /// goes. See [OutputMode]. Future runCommand(String executable, List arguments, { - String workingDirectory, - Map environment, + String? workingDirectory, + Map? environment, bool expectNonZeroExit = false, - int expectedExitCode, - String failureMessage, + int? expectedExitCode, + String? failureMessage, OutputMode outputMode = OutputMode.print, - bool skip = false, - bool Function(String) removeLine, - void Function(String, io.Process) outputListener, + bool Function(String)? removeLine, + void Function(String, io.Process)? outputListener, }) async { final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}'; final String relativeWorkingDir = path.relative(workingDirectory ?? io.Directory.current.path); - if (skip) { - printProgress('SKIPPING', relativeWorkingDir, commandDescription); - return null; - } final Command command = await startCommand(executable, arguments, workingDirectory: workingDirectory, diff --git a/dev/bots/service_worker_test.dart b/dev/bots/service_worker_test.dart index c5d7295052..3e64ef71f0 100644 --- a/dev/bots/service_worker_test.dart +++ b/dev/bots/service_worker_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:shelf/shelf.dart'; @@ -37,7 +36,7 @@ Future _setAppVersion(int version) async { ); } -Future _rebuildApp({ @required int version }) async { +Future _rebuildApp({ required int version }) async { await _setAppVersion(version); await runCommand( _flutter, @@ -56,7 +55,7 @@ Future _rebuildApp({ @required int version }) async { /// A drop-in replacement for `package:test` expect that can run outside the /// test zone. -void expect(Object actual, Object expected) { +void expect(Object? actual, Object? expected) { final Matcher matcher = wrapMatcher(expected); final Map matchState = {}; if (matcher.matches(actual, matchState)) { @@ -68,7 +67,7 @@ void expect(Object actual, Object expected) { } Future runWebServiceWorkerTest({ - @required bool headless, + required bool headless, }) async { await _rebuildApp(version: 1); @@ -78,25 +77,25 @@ Future runWebServiceWorkerTest({ requestedPathCounts.clear(); } - AppServer server; + AppServer? server; Future waitForAppToLoad(Map waitForCounts) async { print('Waiting for app to load $waitForCounts'); - await Future.any(>[ + await Future.any(>[ () async { while (!waitForCounts.entries.every((MapEntry entry) => (requestedPathCounts[entry.key] ?? 0) >= entry.value)) { await Future.delayed(const Duration(milliseconds: 100)); } }(), - server.onChromeError.then((String error) { + server!.onChromeError.then((String error) { throw Exception('Chrome error: $error'); }), ]); } - String reportedVersion; + String? reportedVersion; Future startAppServer({ - @required String cacheControl, + required String cacheControl, }) async { final int serverPort = await findAvailablePort(); final int browserDebugPort = await findAvailablePort(); @@ -113,7 +112,7 @@ Future runWebServiceWorkerTest({ (Request request) { final String requestedPath = request.url.path; requestedPathCounts.putIfAbsent(requestedPath, () => 0); - requestedPathCounts[requestedPath] += 1; + requestedPathCounts[requestedPath] = requestedPathCounts[requestedPath]! + 1; if (requestedPath == 'CLOSE') { reportedVersion = request.url.queryParameters['version']; return Response.ok('OK'); @@ -158,7 +157,7 @@ Future runWebServiceWorkerTest({ reportedVersion = null; print('With cache: test page reload'); - await server.chrome.reloadPage(); + await server!.chrome.reloadPage(); await waitForAppToLoad({ 'CLOSE': 1, 'flutter_service_worker.js': 1, @@ -175,7 +174,7 @@ Future runWebServiceWorkerTest({ await _rebuildApp(version: 2); // Since we're caching, we need to ignore cache when reloading the page. - await server.chrome.reloadPage(ignoreCache: true); + await server!.chrome.reloadPage(ignoreCache: true); await waitForAppToLoad({ 'CLOSE': 1, 'flutter_service_worker.js': 2, @@ -195,7 +194,7 @@ Future runWebServiceWorkerTest({ expect(reportedVersion, '2'); reportedVersion = null; - await server.stop(); + await server!.stop(); ////////////////////////////////////////////////////// @@ -231,7 +230,7 @@ Future runWebServiceWorkerTest({ reportedVersion = null; print('No cache: test page reload'); - await server.chrome.reloadPage(); + await server!.chrome.reloadPage(); await waitForAppToLoad({ 'CLOSE': 1, 'flutter_service_worker.js': 1, @@ -254,7 +253,7 @@ Future runWebServiceWorkerTest({ // refresh when running Chrome manually as normal. At the time of writing // this test I wasn't able to figure out what's wrong with the way we run // Chrome from tests. - await server.chrome.reloadPage(ignoreCache: true); + await server!.chrome.reloadPage(ignoreCache: true); await waitForAppToLoad({ 'CLOSE': 1, 'flutter_service_worker.js': 1, diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 346c77a60a..8d6213f0ca 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -9,7 +9,6 @@ import 'dart:math' as math; import 'package:file/file.dart' as fs; import 'package:file/local.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'browser.dart'; @@ -26,7 +25,7 @@ typedef ShardRunner = Future Function(); /// /// If the output does not match expectations, the function shall return an /// appropriate error message. -typedef OutputChecker = String Function(CommandResult); +typedef OutputChecker = String? Function(CommandResult); final String exe = Platform.isWindows ? '.exe' : ''; final String bat = Platform.isWindows ? '.bat' : ''; @@ -73,7 +72,7 @@ const String kSubshardKey = 'SUBSHARD'; /// /// The last shard also runs the Web plugin tests. int get webShardCount => Platform.environment.containsKey('WEB_SHARD_COUNT') - ? int.parse(Platform.environment['WEB_SHARD_COUNT']) + ? int.parse(Platform.environment['WEB_SHARD_COUNT']!) : 8; /// Tests that we don't run on Web for compilation reasons. // @@ -148,7 +147,7 @@ Future _validateEngineHash() async { } final String expectedVersion = File(engineVersionFile).readAsStringSync().trim(); final CommandResult result = await runCommand(flutterTester, ['--help'], outputMode: OutputMode.capture); - final String actualVersion = result.flattenedStderr.split('\n').firstWhere((final String line) { + final String actualVersion = result.flattenedStderr!.split('\n').firstWhere((final String line) { return line.startsWith('Flutter Engine Version:'); }); if (!actualVersion.contains(expectedVersion)) { @@ -199,7 +198,7 @@ Future _runSmokeTests() async { path.join('test_smoke_test', 'pending_timer_fail_test.dart'), expectFailure: true, printOutput: false, outputChecker: (CommandResult result) { - return result.flattenedStdout.contains('failingPendingTimerTest') + return result.flattenedStdout!.contains('failingPendingTimerTest') ? null : 'Failed to find the stack trace for the pending Timer.'; }), @@ -250,7 +249,7 @@ Future _runSmokeTests() async { // Smoke tests are special and run first for all test shards. // Run all smoke tests for other shards. // Only shard smoke tests when explicitly specified. - final String shardName = Platform.environment[kShardKey]; + final String? shardName = Platform.environment[kShardKey]; if (shardName == kSmokeTestShardName) { testsToRun = _selectIndexOfTotalSubshard(tests); } else { @@ -261,7 +260,7 @@ Future _runSmokeTests() async { } // Verify that we correctly generated the version file. - final String versionError = await verifyVersion(File(path.join(flutterRoot, 'version'))); + final String? versionError = await verifyVersion(File(path.join(flutterRoot, 'version'))); if (versionError != null) exitWithError([versionError]); } @@ -479,7 +478,7 @@ Future _runExampleProjectBuildTests(FileSystemEntity exampleDirectory) asy } Future _flutterBuildApk(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List additionalArgs = const [], }) async { @@ -492,7 +491,7 @@ Future _flutterBuildApk(String relativePathToApplication, { } Future _flutterBuildIpa(String relativePathToApplication, { - @required bool release, + required bool release, List additionalArgs = const [], bool verifyCaching = false, }) async { @@ -506,7 +505,7 @@ Future _flutterBuildIpa(String relativePathToApplication, { } Future _flutterBuildLinux(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List additionalArgs = const [], }) async { @@ -521,7 +520,7 @@ Future _flutterBuildLinux(String relativePathToApplication, { } Future _flutterBuildMacOS(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List additionalArgs = const [], }) async { @@ -536,7 +535,7 @@ Future _flutterBuildMacOS(String relativePathToApplication, { } Future _flutterBuildWin32(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List additionalArgs = const [], }) async { @@ -554,7 +553,7 @@ Future _flutterBuild( String relativePathToApplication, String platformLabel, String platformBuildName, { - @required bool release, + required bool release, bool verifyCaching = false, List additionalArgs = const [], }) async { @@ -598,11 +597,11 @@ Future _flutterBuild( } bool _allTargetsCached(File performanceFile) { - final Map data = json.decode(performanceFile.readAsStringSync()) - as Map; - final List> targets = (data['targets'] as List) - .cast>(); - return targets.every((Map element) => element['skipped'] == true); + final Map data = json.decode(performanceFile.readAsStringSync()) + as Map; + final List> targets = (data['targets']! as List) + .cast>(); + return targets.every((Map element) => element['skipped'] == true); } Future _flutterBuildDart2js(String relativePathToApplication, String target, { bool expectNonZeroExit = false }) async { @@ -760,7 +759,7 @@ Future _runFrameworkTests() async { expectFailure: true, printOutput: false, outputChecker: (CommandResult result) { - final Iterable matches = httpClientWarning.allMatches(result.flattenedStdout); + final Iterable matches = httpClientWarning.allMatches(result.flattenedStdout!); if (matches == null || matches.isEmpty || matches.length > 1) { return 'Failed to print warning about HttpClientUsage, or printed it too many times.\n' 'stdout:\n${result.flattenedStdout}'; @@ -959,8 +958,8 @@ Future _runWebLongRunningTests() async { /// Runs one of the `dev/integration_tests/web_e2e_tests` tests. Future _runWebE2eTest( String name, { - @required String buildMode, - @required String renderer, + required String buildMode, + required String renderer, }) async { await _runFlutterDriverWebTest( target: path.join('test_driver', '$name.dart'), @@ -971,10 +970,10 @@ Future _runWebE2eTest( } Future _runFlutterDriverWebTest({ - @required String target, - @required String buildMode, - @required String renderer, - @required String testAppDirectory, + required String target, + required String buildMode, + required String renderer, + required String testAppDirectory, bool expectFailure = false, bool silenceBrowserOutput = false, }) async { @@ -987,7 +986,7 @@ Future _runFlutterDriverWebTest({ await runCommand( flutter, [ - ...?flutterTestArgs, + ...flutterTestArgs, 'drive', '--target=$target', '--browser-name=chrome', @@ -1083,7 +1082,7 @@ Future _runWebTreeshakeTest() async { /// plugins version file, when null [flutterPluginsVersionFile] is used. Future getFlutterPluginsVersion({ fs.FileSystem fileSystem = const LocalFileSystem(), - String pluginsVersionFile, + String? pluginsVersionFile, }) async { final File versionFile = fileSystem.file(pluginsVersionFile ?? flutterPluginsVersionFile); final String versionFileContents = await versionFile.readAsString(); @@ -1163,7 +1162,7 @@ Future _runSkpGeneratorTests() async { // // If an existing chromedriver is already available on port 4444, the existing // process is reused and this variable remains null. -Command _chromeDriver; +Command? _chromeDriver; Future _isChromeDriverRunning() async { try { @@ -1208,7 +1207,7 @@ Future _stopChromeDriver() async { return; } print('Stopping chromedriver'); - _chromeDriver.process.kill(); + _chromeDriver!.process.kill(); } /// Exercises the old gallery in a browser for a long period of time, looking @@ -1231,7 +1230,7 @@ Future _runGalleryE2eWebTest(String buildMode, { bool canvasKit = false }) await runCommand( flutter, [ - ...?flutterTestArgs, + ...flutterTestArgs, 'drive', if (canvasKit) '--dart-define=FLUTTER_WEB_USE_SKIA=true', @@ -1315,7 +1314,7 @@ Future _runWebReleaseTest(String target, { await runCommand( flutter, [ - ...?flutterTestArgs, + ...flutterTestArgs, 'build', 'web', '--release', @@ -1394,8 +1393,8 @@ Future _runWebDebugTest(String target, { if (success) { print('${green}Web stack trace integration test passed.$reset'); } else { - print(result.flattenedStdout); - print(result.flattenedStderr); + print(result.flattenedStdout!); + print(result.flattenedStderr!); print('${red}Web stack trace integration test failed.$reset'); exit(1); } @@ -1413,7 +1412,7 @@ Future _runFlutterWebTest(String workingDirectory, List tests) asy // TODO(ferhatb): Run web tests with both rendering backends. '--web-renderer=html', // use html backend for web tests. '--sound-null-safety', // web tests do not autodetect yet. - ...?flutterTestArgs, + ...flutterTestArgs, ...tests, ], workingDirectory: workingDirectory, @@ -1429,17 +1428,17 @@ Future _runFlutterWebTest(String workingDirectory, List tests) asy // dependent targets are only built on some engines). // See https://github.com/flutter/flutter/issues/72368 Future _pubRunTest(String workingDirectory, { - List testPaths, + List? testPaths, bool enableFlutterToolAsserts = true, bool useBuildRunner = false, - String coverage, + String? coverage, bool forceSingleCore = false, - Duration perTestTimeout, + Duration? perTestTimeout, bool includeLocalEngineEnv = false, bool ensurePrecompiledTool = true, }) async { - int cpus; - final String cpuVariable = Platform.environment['CPU']; // CPU is set in cirrus.yml + int? cpus; + final String? cpuVariable = Platform.environment['CPU']; // CPU is set in cirrus.yml if (cpuVariable != null) { cpus = int.tryParse(cpuVariable, radix: 10); if (cpus == null) { @@ -1525,13 +1524,12 @@ Future _pubRunTest(String workingDirectory, { } Future _runFlutterTest(String workingDirectory, { - String script, + String? script, bool expectFailure = false, bool printOutput = true, - OutputChecker outputChecker, + OutputChecker? outputChecker, List options = const [], - bool skip = false, - Map environment, + Map? environment, List tests = const [], }) async { assert(!printOutput || outputChecker == null, 'Output either can be printed or checked but not both'); @@ -1539,7 +1537,7 @@ Future _runFlutterTest(String workingDirectory, { final List args = [ 'test', ...options, - ...?flutterTestArgs, + ...flutterTestArgs, ]; final bool shouldProcessOutput = useFlutterTestFormatter && !expectFailure && !options.contains('--coverage'); @@ -1554,8 +1552,6 @@ Future _runFlutterTest(String workingDirectory, { print('Script: $green$script$reset'); if (!printOutput) print('This is one of the tests that does not normally print output.'); - if (skip) - print('This is one of the tests that is normally skipped in this configuration.'); exit(1); } args.add(script); @@ -1574,12 +1570,11 @@ Future _runFlutterTest(String workingDirectory, { workingDirectory: workingDirectory, expectNonZeroExit: expectFailure, outputMode: outputMode, - skip: skip, environment: environment, ); if (outputChecker != null) { - final String message = outputChecker(result); + final String? message = outputChecker(result); if (message != null) exitWithError([message]); } @@ -1612,7 +1607,7 @@ Future _runFlutterTest(String workingDirectory, { } Map _initGradleEnvironment() { - final String androidSdkRoot = (Platform.environment['ANDROID_HOME']?.isEmpty ?? true) + final String? androidSdkRoot = (Platform.environment['ANDROID_HOME']?.isEmpty ?? true) ? Platform.environment['ANDROID_SDK_ROOT'] : Platform.environment['ANDROID_HOME']; if (androidSdkRoot == null || androidSdkRoot.isEmpty) { @@ -1620,7 +1615,7 @@ Map _initGradleEnvironment() { exit(1); } return { - 'ANDROID_HOME': androidSdkRoot, + 'ANDROID_HOME': androidSdkRoot!, 'ANDROID_SDK_ROOT': androidSdkRoot, }; } @@ -1654,7 +1649,7 @@ Future _processTestOutput( formatter.finish(); } -CiProviders get ciProvider { +CiProviders? get ciProvider { if (Platform.environment['CIRRUS_CI'] == 'true') { return CiProviders.cirrus; } @@ -1668,11 +1663,12 @@ CiProviders get ciProvider { String get branchName { switch(ciProvider) { case CiProviders.cirrus: - return Platform.environment['CIRRUS_BRANCH']; + return Platform.environment['CIRRUS_BRANCH']!; case CiProviders.luci: - return Platform.environment['LUCI_BRANCH']; + return Platform.environment['LUCI_BRANCH']!; + case null: + return ''; } - return ''; } /// Checks the given file's contents to determine if they match the allowed @@ -1680,7 +1676,7 @@ String get branchName { /// /// Returns null if the contents are good. Returns a string if they are bad. /// The string is an error message. -Future verifyVersion(File file) async { +Future verifyVersion(File file) async { final RegExp pattern = RegExp( r'^(\d+)\.(\d+)\.(\d+)((-\d+\.\d+)?\.pre(\.\d+)?)?$'); final String version = await file.readAsString(); @@ -1705,7 +1701,7 @@ Future verifyVersion(File file) async { /// 3_3 List _selectIndexOfTotalSubshard(List tests, {String subshardKey = kSubshardKey}) { // Example: "1_3" means the first (one-indexed) shard of three total shards. - final String subshardName = Platform.environment[subshardKey]; + final String? subshardName = Platform.environment[subshardKey]; if (subshardName == null) { print('$kSubshardKey environment variable is missing, skipping sharding'); return tests; @@ -1713,14 +1709,14 @@ List _selectIndexOfTotalSubshard(List tests, {String subshardKey = kSub print('$bold$subshardKey=$subshardName$reset'); final RegExp pattern = RegExp(r'^(\d+)_(\d+)$'); - final Match match = pattern.firstMatch(subshardName); + final Match? match = pattern.firstMatch(subshardName); if (match == null || match.groupCount != 2) { print('${red}Invalid subshard name "$subshardName". Expected format "[int]_[int]" ex. "1_3"'); exit(1); } // One-indexed. - final int index = int.parse(match.group(1)); - final int total = int.parse(match.group(2)); + final int index = int.parse(match!.group(1)!); + final int total = int.parse(match.group(2)!); if (index > total) { print('${red}Invalid subshard name "$subshardName". Index number must be greater or equal to total.'); exit(1); @@ -1760,16 +1756,16 @@ Future selectSubshard(Map subshards) => _runFromList( const String CIRRUS_TASK_NAME = 'CIRRUS_TASK_NAME'; Future _runFromList(Map items, String key, String name, int positionInTaskName) async { - String item = Platform.environment[key]; + String? item = Platform.environment[key]; if (item == null && Platform.environment.containsKey(CIRRUS_TASK_NAME)) { - final List parts = Platform.environment[CIRRUS_TASK_NAME].split('-'); + final List parts = Platform.environment[CIRRUS_TASK_NAME]!.split('-'); assert(positionInTaskName < parts.length); item = parts[positionInTaskName]; } if (item == null) { for (final String currentItem in items.keys) { print('$bold$key=$currentItem$reset'); - await items[currentItem](); + await items[currentItem]!(); print(''); } } else { @@ -1779,6 +1775,6 @@ Future _runFromList(Map items, String key, String nam exit(1); } print('$bold$key=$item$reset'); - await items[item](); + await items[item]!(); } } diff --git a/dev/bots/test/prepare_package_test.dart b/dev/bots/test/prepare_package_test.dart index 509d0f9f92..1db1282bbb 100644 --- a/dev/bots/test/prepare_package_test.dart +++ b/dev/bots/test/prepare_package_test.dart @@ -74,16 +74,16 @@ void main() { }); }); group('ArchiveCreator for $platformName', () { - ArchiveCreator creator; - Directory tempDir; + late ArchiveCreator creator; + late Directory tempDir; Directory flutterDir; Directory cacheDir; - FakeProcessManager processManager; + late FakeProcessManager processManager; final List> args = >[]; final List> namedArgs = >[]; - String flutter; + late String flutter; - Future fakeHttpReader(Uri url, {Map headers}) { + Future fakeHttpReader(Uri url, {Map? headers}) { return Future.value(Uint8List(0)); } @@ -118,7 +118,7 @@ void main() { final String archiveName = path.join(tempDir.absolute.path, 'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}'); - processManager.addCommands(convertResults(>{ + processManager.addCommands(convertResults(?>{ 'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null, 'git reset --hard $testRef': null, 'git remote set-url origin https://github.com/flutter/flutter.git': null, @@ -147,7 +147,7 @@ void main() { final String createBase = path.join(tempDir.absolute.path, 'create_'); final String archiveName = path.join(tempDir.absolute.path, 'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}'); - final Map> calls = >{ + final Map?> calls = ?>{ 'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null, 'git reset --hard $testRef': null, 'git remote set-url origin https://github.com/flutter/flutter.git': null, @@ -197,7 +197,7 @@ void main() { final String createBase = path.join(tempDir.absolute.path, 'create_'); final String archiveName = path.join(tempDir.absolute.path, 'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}'); - final Map> calls = >{ + final Map?> calls = ?>{ 'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null, 'git reset --hard $testRef': null, 'git remote set-url origin https://github.com/flutter/flutter.git': null, @@ -239,7 +239,7 @@ void main() { 'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}'); final ProcessResult codesignFailure = ProcessResult(1, 1, '', 'code object is not signed at all'); final String binPath = path.join(tempDir.path, 'flutter', 'bin', 'cache', 'dart-sdk', 'bin', 'dart'); - final Map> calls = >{ + final Map?> calls = ?>{ 'git clone -b dev https://chromium.googlesource.com/external/github.com/flutter/flutter': null, 'git reset --hard $testRef': null, 'git remote set-url origin https://github.com/flutter/flutter.git': null, @@ -286,8 +286,8 @@ void main() { }); group('ArchivePublisher for $platformName', () { - FakeProcessManager processManager; - Directory tempDir; + late FakeProcessManager processManager; + late Directory tempDir; final String gsutilCall = platform.isWindows ? 'python ${path.join("D:", "depot_tools", "gsutil.py")}' : 'gsutil.py'; @@ -346,7 +346,7 @@ void main() { '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map> calls = >{ + final Map?> calls = ?>{ // This process fails because the file does NOT already exist '$gsutilCall -- stat $gsArchivePath': [ProcessResult(0, 1, '', '')], '$gsutilCall -- rm $gsArchivePath': null, @@ -442,7 +442,7 @@ void main() { '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map> calls = >{ + final Map?> calls = ?>{ // This process fails because the file does NOT already exist '$gsutilCall -- stat $gsArchivePath': [ProcessResult(0, 1, '', '')], '$gsutilCall -- rm $gsArchivePath': null, @@ -552,7 +552,7 @@ void main() { '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map> calls = >{ + final Map?> calls = ?>{ '$gsutilCall -- rm $gsArchivePath': null, '$gsutilCall -- -h Content-Type:$archiveMime cp $archivePath $gsArchivePath': null, '$gsutilCall -- cp $gsJsonPath $jsonPath': null, @@ -567,10 +567,10 @@ void main() { } } -List convertResults(Map> results) { +List convertResults(Map?> results) { final List commands = []; for (final String key in results.keys) { - final List candidates = results[key]; + final List? candidates = results[key]; final List args = key.split(' '); if (candidates == null) { commands.add(FakeCommand( @@ -581,8 +581,8 @@ List convertResults(Map> results) { commands.add(FakeCommand( command: args, exitCode: result.exitCode, - stderr: result.stderr?.toString(), - stdout: result.stdout?.toString(), + stderr: result.stderr.toString(), + stdout: result.stdout.toString(), )); } } diff --git a/dev/bots/test/sdk_directory_has_space_test.dart b/dev/bots/test/sdk_directory_has_space_test.dart index 8a4704f7e5..f5578f3e8c 100644 --- a/dev/bots/test/sdk_directory_has_space_test.dart +++ b/dev/bots/test/sdk_directory_has_space_test.dart @@ -12,10 +12,10 @@ void main() { test('We are in a directory with a space in it', () async { // The Flutter SDK should be in a directory with a space in it, to make sure // our tools support that. - final String expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE']; + final String? expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE']; expect(expectedName, 'flutter sdk'); expect(expectedName, contains(' ')); final List parts = path.split(Directory.current.absolute.path); - expect(parts.reversed.take(3), ['bots', 'dev', expectedName]); + expect(parts.reversed.take(3), ['bots', 'dev', expectedName]); }, skip: true); // https://github.com/flutter/flutter/issues/62919 } diff --git a/dev/bots/test/test_test.dart b/dev/bots/test/test_test.dart index 83565ca9c5..d1030f9197 100644 --- a/dev/bots/test/test_test.dart +++ b/dev/bots/test/test_test.dart @@ -23,7 +23,7 @@ void expectExitCode(ProcessResult result, int expectedExitCode) { void main() { group('verifyVersion()', () { - MemoryFileSystem fileSystem; + late MemoryFileSystem fileSystem; setUp(() { fileSystem = MemoryFileSystem.test(); @@ -97,7 +97,7 @@ void main() { const ProcessManager processManager = LocalProcessManager(); Future runScript( - [Map environment, List otherArgs = const []]) async { + [Map? environment, List otherArgs = const []]) async { final String dart = path.absolute( path.join('..', '..', 'bin', 'cache', 'dart-sdk', 'bin', 'dart')); final ProcessResult scriptProcess = processManager.runSync([ diff --git a/dev/bots/unpublish_package.dart b/dev/bots/unpublish_package.dart index dfe9d6edd4..3e8e2bb42b 100644 --- a/dev/bots/unpublish_package.dart +++ b/dev/bots/unpublish_package.dart @@ -32,7 +32,7 @@ class UnpublishException implements Exception { UnpublishException(this.message, [this.result]); final String message; - final ProcessResult result; + final ProcessResult? result; int get exitCode => result?.exitCode ?? -1; @override @@ -41,7 +41,7 @@ class UnpublishException implements Exception { if (message != null) { output += ': $message'; } - final String stderr = result?.stderr as String ?? ''; + final String stderr = result?.stderr as String? ?? ''; if (stderr.isNotEmpty) { output += ':\n$stderr'; } @@ -60,10 +60,9 @@ String getChannelName(Channel channel) { case Channel.stable: return 'stable'; } - return null; } -Channel fromChannelName(String name) { +Channel fromChannelName(String? name) { switch (name) { case 'beta': return Channel.beta; @@ -87,7 +86,6 @@ String getPublishedPlatform(PublishedPlatform platform) { case PublishedPlatform.windows: return 'windows'; } - return null; } PublishedPlatform fromPublishedPlatform(String name) { @@ -135,10 +133,10 @@ class ProcessRunner { /// Sets the default directory used when `workingDirectory` is not specified /// to [runProcess]. - final Directory defaultWorkingDirectory; + final Directory? defaultWorkingDirectory; /// The environment to run processes with. - Map environment; + late Map environment; /// Run the command and arguments in `commandLine` as a sub-process from /// `workingDirectory` if set, or the [defaultWorkingDirectory] if not. Uses @@ -148,7 +146,7 @@ class ProcessRunner { /// command completes with a non-zero exit code. Future runProcess( List commandLine, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { workingDirectory ??= defaultWorkingDirectory ?? Directory.current; @@ -158,7 +156,7 @@ class ProcessRunner { final List output = []; final Completer stdoutComplete = Completer(); final Completer stderrComplete = Completer(); - Process process; + late Process process; Future allComplete() async { await stderrComplete.future; await stdoutComplete.future; @@ -221,12 +219,12 @@ class ArchiveUnpublisher { this.channels, this.platform, { this.confirmed = false, - ProcessManager processManager, + ProcessManager? processManager, bool subprocessOutput = true, }) : assert(revisionsBeingRemoved.length == 40), metadataGsPath = '$gsReleaseFolder/${getMetadataFilename(platform)}', _processRunner = ProcessRunner( - processManager: processManager, + processManager: processManager ?? const LocalProcessManager(), subprocessOutput: subprocessOutput, ); @@ -249,8 +247,8 @@ class ArchiveUnpublisher { final Map> paths = await _getArchivePaths(releases); releases.removeWhere((Map value) => revisionsBeingRemoved.contains(value['hash']) && channels.contains(fromChannelName(value['channel']))); releases.sort((Map a, Map b) { - final DateTime aDate = DateTime.parse(a['release_date']); - final DateTime bDate = DateTime.parse(b['release_date']); + final DateTime aDate = DateTime.parse(a['release_date']!); + final DateTime bDate = DateTime.parse(b['release_date']!); return bDate.compareTo(aDate); }); jsonData['releases'] = releases; @@ -277,12 +275,12 @@ class ArchiveUnpublisher { final Set hashes = {}; final Map> paths = >{}; for (final Map revision in releases) { - final String hash = revision['hash']; + final String hash = revision['hash']!; final Channel channel = fromChannelName(revision['channel']); hashes.add(hash); if (revisionsBeingRemoved.contains(hash) && channels.contains(channel)) { paths[channel] ??= {}; - paths[channel][hash] = revision['archive']; + paths[channel]![hash] = revision['archive']!; } } final Set missingRevisions = revisionsBeingRemoved.difference(hashes.intersection(revisionsBeingRemoved)); @@ -330,7 +328,7 @@ class ArchiveUnpublisher { Future _runGsUtil( List args, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, bool confirm = false, }) async { @@ -351,7 +349,7 @@ class ArchiveUnpublisher { final List files = []; print('${confirmed ? 'Removing' : 'Would remove'} the following release archives:'); for (final Channel channel in paths.keys) { - final Map hashes = paths[channel]; + final Map hashes = paths[channel]!; for (final String hash in hashes.keys) { final String file = '$gsReleaseFolder/${hashes[hash]}'; files.add(file); @@ -367,7 +365,7 @@ class ArchiveUnpublisher { // We often don't have permission to overwrite, but // we have permission to remove, so that's what we do first. await _runGsUtil(['rm', dest], failOk: true, confirm: confirmed); - String mimeType; + String? mimeType; if (dest.endsWith('.tar.xz')) { mimeType = 'application/x-gtar'; } @@ -497,8 +495,8 @@ Future main(List rawArguments) async { final List platformOptions = platformArg.isNotEmpty ? platformArg : allowedPlatformNames; final List platforms = platformOptions.map((String value) => fromPublishedPlatform(value)).toList(); int exitCode = 0; - String message; - String stack; + late String message; + late String stack; try { for (final PublishedPlatform platform in platforms) { final ArchiveUnpublisher publisher = ArchiveUnpublisher(