Migrate dev/bots to null safety (#86522)
diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index dc98d75..e24c1fd5 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart
@@ -167,17 +167,17 @@ } 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 @@ 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 @@ 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 @@ } Future<void> 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 @@ final List<File> 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 @@ 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 @@ } 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 @@ } for (final String package in dependencyMap.keys) { - final List<String> loop = _deepSearch<String>(dependencyMap, package); + final List<String>? loop = _deepSearch<String>(dependencyMap, package); if (loop != null) { errors.add('${yellow}Dependency loop:$reset ${loop.join(' depends on ')}'); } @@ -973,7 +973,7 @@ const Hash256(0x63D2ABD0041C3E3B, 0x4B52AD8D382353B5, 0x3C51C6785E76CE56, 0xED9DACAD2D2E31C4), }; -Future<void> verifyNoBinaries(String workingDirectory, { Set<Hash256> legacyBinaries }) async { +Future<void> verifyNoBinaries(String workingDirectory, { Set<Hash256>? 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 @@ .toList(); } -Stream<File> _allFiles(String workingDirectory, String extension, { @required int minimumMatches }) async* { +Stream<File> _allFiles(String workingDirectory, String? extension, { required int minimumMatches }) async* { final Set<String> gitFileNamesSet = <String>{}; gitFileNamesSet.addAll((await _gitFiles(workingDirectory)).map((File f) => path.canonicalize(f.absolute.path))); @@ -1101,8 +1101,8 @@ class EvalResult { EvalResult({ - this.stdout, - this.stderr, + required this.stdout, + required this.stderr, this.exitCode = 0, }); @@ -1113,18 +1113,13 @@ // TODO(ianh): Refactor this to reuse the code in run_command.dart Future<EvalResult> _evalCommand(String executable, List<String> arguments, { - @required String workingDirectory, - Map<String, String> environment, - bool skip = false, + required String workingDirectory, + Map<String, String>? 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 @@ '--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<String> dependencySet = <String>{}; @@ -1217,7 +1212,7 @@ } } -Future<void> _runFlutterAnalyze(String workingDirectory, { +Future<CommandResult> _runFlutterAnalyze(String workingDirectory, { List<String> options = const <String>[], }) async { return runCommand( @@ -1235,9 +1230,9 @@ .map<Set<String>>((File file) { final Set<String> result = <String>{}; 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 @@ } return result; }) - .reduce((Set<String> value, Set<String> element) { + .reduce((Set<String>? value, Set<String> element) { value ??= <String>{}; value.addAll(element); return value; }); } -List<T> _deepSearch<T>(Map<T, Set<T>> map, T start, [ Set<T> seen ]) { +List<T>? _deepSearch<T>(Map<T, Set<T>> map, T start, [ Set<T>? 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 <T>[start, key]; - final List<T> result = _deepSearch<T>( + final List<T>? result = _deepSearch<T>( map, key, <T>{
diff --git a/dev/bots/browser.dart b/dev/bots/browser.dart index 0b0651e..e0303db 100644 --- a/dev/bots/browser.dart +++ b/dev/bots/browser.dart
@@ -6,7 +6,6 @@ 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 @@ /// 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<String> 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<String> resultCompleter = Completer<String>(); server = await io.HttpServer.bind('localhost', serverPort); @@ -63,13 +62,13 @@ AppServer._(this._server, this.chrome, this.onChromeError); static Future<AppServer> 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<Handler> additionalRequestHandlers, + List<Handler>? additionalRequestHandlers, }) async { io.HttpServer server; Chrome chrome; @@ -106,7 +105,7 @@ final Chrome chrome; Future<void> 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 0b5552c..9bb08fd 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 @@ /// /// 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 @@ return null; } final Map<String, dynamic> decoded = json.decode(raw) as Map<String, dynamic>; - 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 @@ _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 @@ case TestStatus.failed: failed.addAll(<String>[ '$_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 @@ /// 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 @@ /// 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 4c88c79..e3f3e5c 100644 --- a/dev/bots/prepare_package.dart +++ b/dev/bots/prepare_package.dart
@@ -11,7 +11,6 @@ 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 @@ 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 @@ 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 @@ case Branch.stable: return 'stable'; } - return null; } Branch fromBranchName(String name) { @@ -81,7 +79,7 @@ /// properly without dropping any. class ProcessRunner { ProcessRunner({ - ProcessManager processManager, + ProcessManager? processManager, this.subprocessOutput = true, this.defaultWorkingDirectory, this.platform = const LocalPlatform(), @@ -102,10 +100,10 @@ /// 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<String, String> environment; + late Map<String, String> 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 @@ /// command completes with a non-zero exit code. Future<String> runProcess( List<String> commandLine, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { workingDirectory ??= defaultWorkingDirectory ?? Directory.current; @@ -125,7 +123,7 @@ final List<int> output = <int>[]; final Completer<void> stdoutComplete = Completer<void>(); final Completer<void> stderrComplete = Completer<void>(); - Process process; + late Process process; Future<int> allComplete() async { await stderrComplete.future; await stdoutComplete.future; @@ -197,10 +195,10 @@ 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 @@ /// [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 @@ } } - Future<String> _runFlutter(List<String> args, {Directory workingDirectory}) { + Future<String> _runFlutter(List<String> args, {Directory? workingDirectory}) { return _processRunner.runProcess( <String>[_flutter, ...args], workingDirectory: workingDirectory ?? flutterRoot, ); } - Future<String> _runGit(List<String> args, {Directory workingDirectory}) { + Future<String> _runGit(List<String> args, {Directory? workingDirectory}) { return _processRunner.runProcess( <String>['git', ...args], workingDirectory: workingDirectory ?? flutterRoot, @@ -462,7 +460,7 @@ /// Unpacks the given zip file into the currentDirectory (if set), or the /// same directory as the archive. - Future<String> _unzipArchive(File archive, {Directory workingDirectory}) { + Future<String> _unzipArchive(File archive, {Directory? workingDirectory}) { workingDirectory ??= Directory(path.dirname(archive.absolute.path)); List<String> commandLine; if (platform.isWindows) { @@ -532,7 +530,7 @@ 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 @@ Future<String> _runGsUtil( List<String> args, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { if (dryRun) { @@ -671,7 +669,7 @@ } if (platform.isWindows) { return _processRunner.runProcess( - <String>['python', path.join(platform.environment['DEPOT_TOOLS'], 'gsutil.py'), '--', ...args], + <String>['python', path.join(platform.environment['DEPOT_TOOLS']!, 'gsutil.py'), '--', ...args], workingDirectory: workingDirectory, failOk: failOk, ); @@ -699,14 +697,14 @@ } Future<String> _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(<String>['rm', dest], failOk: true); - String mimeType; + String? mimeType; if (dest.endsWith('.tar.xz')) { mimeType = 'application/x-gtar'; } @@ -841,7 +839,7 @@ 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 9bbd7fd..2d5579e 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml
@@ -2,7 +2,7 @@ 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 bee2a69..13a97f2 100644 --- a/dev/bots/run_command.dart +++ b/dev/bots/run_command.dart
@@ -19,12 +19,12 @@ /// code fails the test immediately by exiting the test process with exit code /// 1. Stream<String> runAndGetStdout(String executable, List<String> arguments, { - String workingDirectory, - Map<String, String> environment, + String? workingDirectory, + Map<String, String>? environment, bool expectNonZeroExit = false, }) async* { final StreamController<String> output = StreamController<String>(); - final Future<CommandResult> command = runCommand( + final Future<CommandResult?> command = runCommand( executable, arguments, workingDirectory: workingDirectory, @@ -52,8 +52,8 @@ final io.Process process; final Stopwatch _time; - final Future<List<List<int>>> _savedStdout; - final Future<List<List<int>>> _savedStderr; + final Future<List<List<int>>>? _savedStdout; + final Future<List<List<int>>>? _savedStderr; /// Evaluates when the [process] exits. /// @@ -63,8 +63,8 @@ _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 @@ 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 @@ /// `outputMode` controls where the standard output from the command process /// goes. See [OutputMode]. Future<Command> startCommand(String executable, List<String> arguments, { - String workingDirectory, - Map<String, String> environment, + String? workingDirectory, + Map<String, String>? 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 @@ environment: environment, ); - Future<List<List<int>>> savedStdout, savedStderr; + Future<List<List<int>>>? savedStdout, savedStderr; final Stream<List<int>> stdoutSource = process.stdout .transform<String>(const Utf8Decoder()) .transform(const LineSplitter()) @@ -150,27 +150,22 @@ /// 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<CommandResult> runCommand(String executable, List<String> arguments, { - String workingDirectory, - Map<String, String> environment, + String? workingDirectory, + Map<String, String>? 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 c5d7295..3e64ef7 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<void> _rebuildApp({ @required int version }) async { +Future<void> _rebuildApp({ required int version }) async { await _setAppVersion(version); await runCommand( _flutter, @@ -56,7 +55,7 @@ /// 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<Object, Object> matchState = <Object, Object>{}; if (matcher.matches(actual, matchState)) { @@ -68,7 +67,7 @@ } Future<void> runWebServiceWorkerTest({ - @required bool headless, + required bool headless, }) async { await _rebuildApp(version: 1); @@ -78,25 +77,25 @@ requestedPathCounts.clear(); } - AppServer server; + AppServer? server; Future<void> waitForAppToLoad(Map<String, int> waitForCounts) async { print('Waiting for app to load $waitForCounts'); - await Future.any(<Future<void>>[ + await Future.any(<Future<Object?>>[ () async { while (!waitForCounts.entries.every((MapEntry<String, int> entry) => (requestedPathCounts[entry.key] ?? 0) >= entry.value)) { await Future<void>.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<void> startAppServer({ - @required String cacheControl, + required String cacheControl, }) async { final int serverPort = await findAvailablePort(); final int browserDebugPort = await findAvailablePort(); @@ -113,7 +112,7 @@ (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 @@ reportedVersion = null; print('With cache: test page reload'); - await server.chrome.reloadPage(); + await server!.chrome.reloadPage(); await waitForAppToLoad(<String, int>{ 'CLOSE': 1, 'flutter_service_worker.js': 1, @@ -175,7 +174,7 @@ 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(<String, int>{ 'CLOSE': 1, 'flutter_service_worker.js': 2, @@ -195,7 +194,7 @@ expect(reportedVersion, '2'); reportedVersion = null; - await server.stop(); + await server!.stop(); ////////////////////////////////////////////////////// @@ -231,7 +230,7 @@ reportedVersion = null; print('No cache: test page reload'); - await server.chrome.reloadPage(); + await server!.chrome.reloadPage(); await waitForAppToLoad(<String, int>{ 'CLOSE': 1, 'flutter_service_worker.js': 1, @@ -254,7 +253,7 @@ // 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(<String, int>{ 'CLOSE': 1, 'flutter_service_worker.js': 1,
diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 346c77a..8d6213f 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart
@@ -9,7 +9,6 @@ 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 @@ /// /// 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 @@ /// /// 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 @@ } final String expectedVersion = File(engineVersionFile).readAsStringSync().trim(); final CommandResult result = await runCommand(flutterTester, <String>['--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 @@ 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 @@ // 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<ShardRunner>(tests); } else { @@ -261,7 +260,7 @@ } // 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(<String>[versionError]); } @@ -479,7 +478,7 @@ } Future<void> _flutterBuildApk(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List<String> additionalArgs = const <String>[], }) async { @@ -492,7 +491,7 @@ } Future<void> _flutterBuildIpa(String relativePathToApplication, { - @required bool release, + required bool release, List<String> additionalArgs = const <String>[], bool verifyCaching = false, }) async { @@ -506,7 +505,7 @@ } Future<void> _flutterBuildLinux(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List<String> additionalArgs = const <String>[], }) async { @@ -521,7 +520,7 @@ } Future<void> _flutterBuildMacOS(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List<String> additionalArgs = const <String>[], }) async { @@ -536,7 +535,7 @@ } Future<void> _flutterBuildWin32(String relativePathToApplication, { - @required bool release, + required bool release, bool verifyCaching = false, List<String> additionalArgs = const <String>[], }) async { @@ -554,7 +553,7 @@ String relativePathToApplication, String platformLabel, String platformBuildName, { - @required bool release, + required bool release, bool verifyCaching = false, List<String> additionalArgs = const <String>[], }) async { @@ -598,11 +597,11 @@ } bool _allTargetsCached(File performanceFile) { - final Map<String, Object> data = json.decode(performanceFile.readAsStringSync()) - as Map<String, Object>; - final List<Map<String, Object>> targets = (data['targets'] as List<Object>) - .cast<Map<String, Object>>(); - return targets.every((Map<String, Object> element) => element['skipped'] == true); + final Map<String, Object?> data = json.decode(performanceFile.readAsStringSync()) + as Map<String, Object?>; + final List<Map<String, Object?>> targets = (data['targets']! as List<Object?>) + .cast<Map<String, Object?>>(); + return targets.every((Map<String, Object?> element) => element['skipped'] == true); } Future<void> _flutterBuildDart2js(String relativePathToApplication, String target, { bool expectNonZeroExit = false }) async { @@ -760,7 +759,7 @@ expectFailure: true, printOutput: false, outputChecker: (CommandResult result) { - final Iterable<Match> matches = httpClientWarning.allMatches(result.flattenedStdout); + final Iterable<Match> 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 @@ /// Runs one of the `dev/integration_tests/web_e2e_tests` tests. Future<void> _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<void> _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 @@ await runCommand( flutter, <String>[ - ...?flutterTestArgs, + ...flutterTestArgs, 'drive', '--target=$target', '--browser-name=chrome', @@ -1083,7 +1082,7 @@ /// plugins version file, when null [flutterPluginsVersionFile] is used. Future<String> 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 @@ // // 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<bool> _isChromeDriverRunning() async { try { @@ -1208,7 +1207,7 @@ 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 @@ await runCommand( flutter, <String>[ - ...?flutterTestArgs, + ...flutterTestArgs, 'drive', if (canvasKit) '--dart-define=FLUTTER_WEB_USE_SKIA=true', @@ -1315,7 +1314,7 @@ await runCommand( flutter, <String>[ - ...?flutterTestArgs, + ...flutterTestArgs, 'build', 'web', '--release', @@ -1394,8 +1393,8 @@ 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 @@ // 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 @@ // dependent targets are only built on some engines). // See https://github.com/flutter/flutter/issues/72368 Future<void> _pubRunTest(String workingDirectory, { - List<String> testPaths, + List<String>? 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<void> _runFlutterTest(String workingDirectory, { - String script, + String? script, bool expectFailure = false, bool printOutput = true, - OutputChecker outputChecker, + OutputChecker? outputChecker, List<String> options = const <String>[], - bool skip = false, - Map<String, String> environment, + Map<String, String>? environment, List<String> tests = const <String>[], }) async { assert(!printOutput || outputChecker == null, 'Output either can be printed or checked but not both'); @@ -1539,7 +1537,7 @@ final List<String> args = <String>[ 'test', ...options, - ...?flutterTestArgs, + ...flutterTestArgs, ]; final bool shouldProcessOutput = useFlutterTestFormatter && !expectFailure && !options.contains('--coverage'); @@ -1554,8 +1552,6 @@ 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 @@ 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(<String>[message]); } @@ -1612,7 +1607,7 @@ } Map<String, String> _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 @@ exit(1); } return <String, String>{ - 'ANDROID_HOME': androidSdkRoot, + 'ANDROID_HOME': androidSdkRoot!, 'ANDROID_SDK_ROOT': androidSdkRoot, }; } @@ -1654,7 +1649,7 @@ formatter.finish(); } -CiProviders get ciProvider { +CiProviders? get ciProvider { if (Platform.environment['CIRRUS_CI'] == 'true') { return CiProviders.cirrus; } @@ -1668,11 +1663,12 @@ 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 @@ /// /// Returns null if the contents are good. Returns a string if they are bad. /// The string is an error message. -Future<String> verifyVersion(File file) async { +Future<String?> 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 @@ /// 3_3 List<T> _selectIndexOfTotalSubshard<T>(List<T> 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 @@ 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 @@ const String CIRRUS_TASK_NAME = 'CIRRUS_TASK_NAME'; Future<void> _runFromList(Map<String, ShardRunner> 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<String> parts = Platform.environment[CIRRUS_TASK_NAME].split('-'); + final List<String> 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 @@ 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 509d0f9..1db1282 100644 --- a/dev/bots/test/prepare_package_test.dart +++ b/dev/bots/test/prepare_package_test.dart
@@ -74,16 +74,16 @@ }); }); 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<List<String>> args = <List<String>>[]; final List<Map<Symbol, dynamic>> namedArgs = <Map<Symbol, dynamic>>[]; - String flutter; + late String flutter; - Future<Uint8List> fakeHttpReader(Uri url, {Map<String, String> headers}) { + Future<Uint8List> fakeHttpReader(Uri url, {Map<String, String>? headers}) { return Future<Uint8List>.value(Uint8List(0)); } @@ -118,7 +118,7 @@ final String archiveName = path.join(tempDir.absolute.path, 'flutter_${platformName}_v1.2.3-dev${platform.isLinux ? '.tar.xz' : '.zip'}'); - processManager.addCommands(convertResults(<String, List<ProcessResult>>{ + processManager.addCommands(convertResults(<String, List<ProcessResult>?>{ '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 @@ 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<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ '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 @@ 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<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ '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 @@ '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<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ '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 @@ }); 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 @@ '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ // This process fails because the file does NOT already exist '$gsutilCall -- stat $gsArchivePath': <ProcessResult>[ProcessResult(0, 1, '', '')], '$gsutilCall -- rm $gsArchivePath': null, @@ -442,7 +442,7 @@ '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ // This process fails because the file does NOT already exist '$gsutilCall -- stat $gsArchivePath': <ProcessResult>[ProcessResult(0, 1, '', '')], '$gsutilCall -- rm $gsArchivePath': null, @@ -552,7 +552,7 @@ '''; File(jsonPath).writeAsStringSync(releasesJson); File(archivePath).writeAsStringSync('archive contents'); - final Map<String, List<ProcessResult>> calls = <String, List<ProcessResult>>{ + final Map<String, List<ProcessResult>?> calls = <String, List<ProcessResult>?>{ '$gsutilCall -- rm $gsArchivePath': null, '$gsutilCall -- -h Content-Type:$archiveMime cp $archivePath $gsArchivePath': null, '$gsutilCall -- cp $gsJsonPath $jsonPath': null, @@ -567,10 +567,10 @@ } } -List<FakeCommand> convertResults(Map<String, List<ProcessResult>> results) { +List<FakeCommand> convertResults(Map<String, List<ProcessResult>?> results) { final List<FakeCommand> commands = <FakeCommand>[]; for (final String key in results.keys) { - final List<ProcessResult> candidates = results[key]; + final List<ProcessResult>? candidates = results[key]; final List<String> args = key.split(' '); if (candidates == null) { commands.add(FakeCommand( @@ -581,8 +581,8 @@ 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 8a4704f..f5578f3 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 @@ 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<String> parts = path.split(Directory.current.absolute.path); - expect(parts.reversed.take(3), <String>['bots', 'dev', expectedName]); + expect(parts.reversed.take(3), <String?>['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 83565ca..d1030f9 100644 --- a/dev/bots/test/test_test.dart +++ b/dev/bots/test/test_test.dart
@@ -23,7 +23,7 @@ void main() { group('verifyVersion()', () { - MemoryFileSystem fileSystem; + late MemoryFileSystem fileSystem; setUp(() { fileSystem = MemoryFileSystem.test(); @@ -97,7 +97,7 @@ const ProcessManager processManager = LocalProcessManager(); Future<ProcessResult> runScript( - [Map<String, String> environment, List<String> otherArgs = const <String>[]]) async { + [Map<String, String>? environment, List<String> otherArgs = const <String>[]]) async { final String dart = path.absolute( path.join('..', '..', 'bin', 'cache', 'dart-sdk', 'bin', 'dart')); final ProcessResult scriptProcess = processManager.runSync(<String>[
diff --git a/dev/bots/unpublish_package.dart b/dev/bots/unpublish_package.dart index dfe9d6e..3e8e2bb 100644 --- a/dev/bots/unpublish_package.dart +++ b/dev/bots/unpublish_package.dart
@@ -32,7 +32,7 @@ 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 @@ 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 @@ 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 @@ case PublishedPlatform.windows: return 'windows'; } - return null; } PublishedPlatform fromPublishedPlatform(String name) { @@ -135,10 +133,10 @@ /// 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<String, String> environment; + late Map<String, String> 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 @@ /// command completes with a non-zero exit code. Future<String> runProcess( List<String> commandLine, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, }) async { workingDirectory ??= defaultWorkingDirectory ?? Directory.current; @@ -158,7 +156,7 @@ final List<int> output = <int>[]; final Completer<void> stdoutComplete = Completer<void>(); final Completer<void> stderrComplete = Completer<void>(); - Process process; + late Process process; Future<int> allComplete() async { await stderrComplete.future; await stdoutComplete.future; @@ -221,12 +219,12 @@ 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 @@ final Map<Channel, Map<String, String>> paths = await _getArchivePaths(releases); releases.removeWhere((Map<String, String> value) => revisionsBeingRemoved.contains(value['hash']) && channels.contains(fromChannelName(value['channel']))); releases.sort((Map<String, String> a, Map<String, String> 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 @@ final Set<String> hashes = <String>{}; final Map<Channel, Map<String, String>> paths = <Channel, Map<String, String>>{}; for (final Map<String, String> 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] ??= <String, String>{}; - paths[channel][hash] = revision['archive']; + paths[channel]![hash] = revision['archive']!; } } final Set<String> missingRevisions = revisionsBeingRemoved.difference(hashes.intersection(revisionsBeingRemoved)); @@ -330,7 +328,7 @@ Future<String> _runGsUtil( List<String> args, { - Directory workingDirectory, + Directory? workingDirectory, bool failOk = false, bool confirm = false, }) async { @@ -351,7 +349,7 @@ final List<String> files = <String>[]; print('${confirmed ? 'Removing' : 'Would remove'} the following release archives:'); for (final Channel channel in paths.keys) { - final Map<String, String> hashes = paths[channel]; + final Map<String, String> hashes = paths[channel]!; for (final String hash in hashes.keys) { final String file = '$gsReleaseFolder/${hashes[hash]}'; files.add(file); @@ -367,7 +365,7 @@ // We often don't have permission to overwrite, but // we have permission to remove, so that's what we do first. await _runGsUtil(<String>['rm', dest], failOk: true, confirm: confirmed); - String mimeType; + String? mimeType; if (dest.endsWith('.tar.xz')) { mimeType = 'application/x-gtar'; } @@ -497,8 +495,8 @@ final List<String> platformOptions = platformArg.isNotEmpty ? platformArg : allowedPlatformNames; final List<PublishedPlatform> platforms = platformOptions.map<PublishedPlatform>((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(