Fix newly enforced package:pedantic lints (#1118)

- always_declare_return_types
- annotate_overrides
- await_only_futures
- omit_local_variable_types
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_final_fields
- prefer_for_elements_to_map_fromiterable
- prefer_if_null_operators
- prefer_spread_collections
- unnecessary_this
- use_function_type_syntax_for_parameters

Bump min SDK to 2.3.0 everywhere to allow using spreads in collection
literals.

Skip an already failing test
diff --git a/.travis.yml b/.travis.yml
index 854d577..da5ba42 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
-# Created with package:mono_repo v2.1.0
+# Created with package:mono_repo v2.3.0
 language: dart
 
 # Custom configuration
@@ -13,43 +13,51 @@
 jobs:
   include:
     - stage: analyze_and_format
-      name: "SDK: dev; PKGS: pkgs/test, pkgs/test_api, pkgs/test_core; TASKS: [`dartfmt -n --set-exit-if-changed .`, `dartanalyzer --fatal-infos --fatal-warnings .`]"
-      dart: dev
-      env: PKGS="pkgs/test pkgs/test_api pkgs/test_core"
-      script: ./tool/travis.sh dartfmt dartanalyzer_0
-    - stage: analyze_and_format
-      name: "SDK: 2.2.0; PKG: pkgs/test, pkgs/test_api, pkgs/test_core; TASKS: `dartanalyzer --fatal-warnings .`"
-      dart: "2.2.0"
+      name: "SDK: 2.3.0; PKGS: pkgs/test, pkgs/test_api, pkgs/test_core; TASKS: `dartanalyzer --fatal-warnings .`"
+      dart: "2.3.0"
+      os: linux
       env: PKGS="pkgs/test pkgs/test_api pkgs/test_core"
       script: ./tool/travis.sh dartanalyzer_1
+    - stage: analyze_and_format
+      name: "SDK: dev; PKGS: pkgs/test, pkgs/test_api, pkgs/test_core; TASKS: [`dartfmt -n --set-exit-if-changed .`, `dartanalyzer --fatal-infos --fatal-warnings .`]"
+      dart: dev
+      os: linux
+      env: PKGS="pkgs/test pkgs/test_api pkgs/test_core"
+      script: ./tool/travis.sh dartfmt dartanalyzer_0
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test; TASKS: `xvfb-run -s \"-screen 0 1024x768x24\" pub run test --preset travis --total-shards 5 --shard-index 0`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test"
       script: ./tool/travis.sh command_0
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test; TASKS: `xvfb-run -s \"-screen 0 1024x768x24\" pub run test --preset travis --total-shards 5 --shard-index 1`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test"
       script: ./tool/travis.sh command_1
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test; TASKS: `xvfb-run -s \"-screen 0 1024x768x24\" pub run test --preset travis --total-shards 5 --shard-index 2`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test"
       script: ./tool/travis.sh command_2
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test; TASKS: `xvfb-run -s \"-screen 0 1024x768x24\" pub run test --preset travis --total-shards 5 --shard-index 3`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test"
       script: ./tool/travis.sh command_3
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test; TASKS: `xvfb-run -s \"-screen 0 1024x768x24\" pub run test --preset travis --total-shards 5 --shard-index 4`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test"
       script: ./tool/travis.sh command_4
     - stage: unit_test
       name: "SDK: dev; PKG: pkgs/test_api; TASKS: `pub run test --preset travis`"
       dart: dev
+      os: linux
       env: PKGS="pkgs/test_api"
       script: ./tool/travis.sh test
 
diff --git a/pkgs/test/lib/src/bootstrap/browser.dart b/pkgs/test/lib/src/bootstrap/browser.dart
index 18583ca..171840e 100644
--- a/pkgs/test/lib/src/bootstrap/browser.dart
+++ b/pkgs/test/lib/src/bootstrap/browser.dart
@@ -8,7 +8,7 @@
 import '../runner/browser/post_message_channel.dart';
 
 /// Bootstraps a browser test to communicate with the test runner.
-void internalBootstrapBrowserTest(Function getMain()) {
+void internalBootstrapBrowserTest(Function Function() getMain) {
   var channel =
       serializeSuite(getMain, hidePrints: false, beforeLoad: () async {
     var serialized =
diff --git a/pkgs/test/lib/src/bootstrap/node.dart b/pkgs/test/lib/src/bootstrap/node.dart
index 23ea2a7..ca002ba 100644
--- a/pkgs/test/lib/src/bootstrap/node.dart
+++ b/pkgs/test/lib/src/bootstrap/node.dart
@@ -8,7 +8,7 @@
 import 'package:test_core/src/util/stack_trace_mapper.dart'; // ignore: implementation_imports
 
 /// Bootstraps a browser test to communicate with the test runner.
-void internalBootstrapNodeTest(Function getMain()) {
+void internalBootstrapNodeTest(Function Function() getMain) {
   var channel = serializeSuite(getMain, beforeLoad: () async {
     var serialized = await suiteChannel('test.node.mapper').stream.first;
     if (serialized == null || serialized is! Map) return;
diff --git a/pkgs/test/lib/src/executable.dart b/pkgs/test/lib/src/executable.dart
index e8313f8..9132c82 100644
--- a/pkgs/test/lib/src/executable.dart
+++ b/pkgs/test/lib/src/executable.dart
@@ -9,7 +9,7 @@
 import 'runner/node/platform.dart';
 import 'runner/browser/platform.dart';
 
-main(List<String> args) async {
+void main(List<String> args) async {
   registerPlatformPlugin([Runtime.nodeJS], () => NodePlatform());
   registerPlatformPlugin([
     Runtime.chrome,
@@ -19,5 +19,6 @@
     Runtime.internetExplorer
   ], () => BrowserPlatform.start());
 
-  await executable.main(args);
+  // TODO figure out if this await is necessary
+  await (executable.main(args) as dynamic);
 }
diff --git a/pkgs/test/lib/src/runner/browser/browser.dart b/pkgs/test/lib/src/runner/browser/browser.dart
index 43c34f2..881dd74 100644
--- a/pkgs/test/lib/src/runner/browser/browser.dart
+++ b/pkgs/test/lib/src/runner/browser/browser.dart
@@ -61,7 +61,7 @@
   /// which asynchronously returns the browser process. Any errors in
   /// [startBrowser] (even those raised asynchronously after it returns) are
   /// piped to [onExit] and will cause the browser to be killed.
-  Browser(Future<Process> startBrowser()) {
+  Browser(Future<Process> Function() startBrowser) {
     // Don't return a Future here because there's no need for the caller to wait
     // for the process to actually start. They should just wait for the HTTP
     // request instead.
@@ -70,7 +70,7 @@
       _processCompleter.complete(process);
 
       var output = Uint8Buffer();
-      drainOutput(Stream<List<int>> stream) {
+      void drainOutput(Stream<List<int>> stream) {
         try {
           _ioSubscriptions
               .add(stream.listen(output.addAll, cancelOnError: true));
@@ -115,7 +115,7 @@
       // Make sure the process dies even if the error wasn't fatal.
       _process.then((process) => process.kill());
 
-      if (stackTrace == null) stackTrace = Trace.current();
+      stackTrace ??= Trace.current();
       if (_onExitCompleter.isCompleted) return;
       _onExitCompleter.completeError(
           ApplicationException(
diff --git a/pkgs/test/lib/src/runner/browser/browser_manager.dart b/pkgs/test/lib/src/runner/browser/browser_manager.dart
index 7213b9b..ce8b74d 100644
--- a/pkgs/test/lib/src/runner/browser/browser_manager.dart
+++ b/pkgs/test/lib/src/runner/browser/browser_manager.dart
@@ -80,7 +80,7 @@
   ///
   /// These are used to mark suites as debugging or not based on the browser's
   /// pings.
-  final _controllers = Set<RunnerSuiteController>();
+  final _controllers = <RunnerSuiteController>{};
 
   // A timer that's reset whenever we receive a message from the browser.
   //
@@ -213,7 +213,7 @@
 
     var suiteID = _suiteID++;
     RunnerSuiteController controller;
-    closeIframe() {
+    void closeIframe() {
       if (_closed) return;
       _controllers.remove(controller);
       _channel.sink.add({'command': 'closeSuite', 'id': suiteID});
@@ -310,16 +310,21 @@
 class _BrowserEnvironment implements Environment {
   final BrowserManager _manager;
 
+  @override
   final supportsDebugging = true;
 
+  @override
   final Uri observatoryUrl;
 
+  @override
   final Uri remoteDebuggerUrl;
 
+  @override
   final Stream onRestart;
 
   _BrowserEnvironment(this._manager, this.observatoryUrl,
       this.remoteDebuggerUrl, this.onRestart);
 
+  @override
   CancelableOperation displayPause() => _manager._displayPause();
 }
diff --git a/pkgs/test/lib/src/runner/browser/chrome.dart b/pkgs/test/lib/src/runner/browser/chrome.dart
index 2fd5229..de76d35 100644
--- a/pkgs/test/lib/src/runner/browser/chrome.dart
+++ b/pkgs/test/lib/src/runner/browser/chrome.dart
@@ -22,8 +22,10 @@
 ///
 /// Any errors starting or running the process are reported through [onExit].
 class Chrome extends Browser {
+  @override
   final name = 'Chrome';
 
+  @override
   final Future<Uri> remoteDebuggerUrl;
 
   /// Starts a new instance of Chrome open to the given [url], which may be a
@@ -86,6 +88,6 @@
     }, remoteDebuggerCompleter.future);
   }
 
-  Chrome._(Future<Process> startBrowser(), this.remoteDebuggerUrl)
+  Chrome._(Future<Process> Function() startBrowser, this.remoteDebuggerUrl)
       : super(startBrowser);
 }
diff --git a/pkgs/test/lib/src/runner/browser/firefox.dart b/pkgs/test/lib/src/runner/browser/firefox.dart
index 6f92d40..06a279a 100644
--- a/pkgs/test/lib/src/runner/browser/firefox.dart
+++ b/pkgs/test/lib/src/runner/browser/firefox.dart
@@ -29,6 +29,7 @@
 ///
 /// Any errors starting or running the process are reported through [onExit].
 class Firefox extends Browser {
+  @override
   final name = 'Firefox';
 
   Firefox(url, {ExecutableSettings settings})
@@ -41,11 +42,15 @@
     var dir = createTempDir();
     File(p.join(dir, 'prefs.js')).writeAsStringSync(_preferences);
 
-    var process = await Process.start(
-        settings.executable,
-        ['--profile', '$dir', url.toString(), '--no-remote']
-          ..addAll(settings.arguments),
-        environment: {'MOZ_CRASHREPORTER_DISABLE': '1'});
+    var process = await Process.start(settings.executable, [
+      '--profile',
+      '$dir',
+      url.toString(),
+      '--no-remote',
+      ...settings.arguments,
+    ], environment: {
+      'MOZ_CRASHREPORTER_DISABLE': '1'
+    });
 
     unawaited(process.exitCode
         .then((_) => Directory(dir).deleteSync(recursive: true)));
diff --git a/pkgs/test/lib/src/runner/browser/internet_explorer.dart b/pkgs/test/lib/src/runner/browser/internet_explorer.dart
index c258ae7..d79c9e4 100644
--- a/pkgs/test/lib/src/runner/browser/internet_explorer.dart
+++ b/pkgs/test/lib/src/runner/browser/internet_explorer.dart
@@ -14,6 +14,7 @@
 ///
 /// Any errors starting or running the process are reported through [onExit].
 class InternetExplorer extends Browser {
+  @override
   final name = 'Internet Explorer';
 
   InternetExplorer(url, {ExecutableSettings settings})
@@ -24,7 +25,10 @@
   static Future<Process> _startBrowser(url, ExecutableSettings settings) {
     settings ??= defaultSettings[Runtime.internetExplorer];
 
-    return Process.start(settings.executable,
-        ['-extoff', url.toString()]..addAll(settings.arguments));
+    return Process.start(settings.executable, [
+      '-extoff',
+      '$url',
+      ...settings.arguments,
+    ]);
   }
 }
diff --git a/pkgs/test/lib/src/runner/browser/phantom_js.dart b/pkgs/test/lib/src/runner/browser/phantom_js.dart
index 5f986b2..2a00ed7 100644
--- a/pkgs/test/lib/src/runner/browser/phantom_js.dart
+++ b/pkgs/test/lib/src/runner/browser/phantom_js.dart
@@ -42,8 +42,10 @@
 ///
 /// Any errors starting or running the process are reported through [onExit].
 class PhantomJS extends Browser {
+  @override
   final name = 'PhantomJS';
 
+  @override
   final Future<Uri> remoteDebuggerUrl;
 
   factory PhantomJS(url, {ExecutableSettings settings, bool debug = false}) {
@@ -88,6 +90,6 @@
     }, remoteDebuggerCompleter.future);
   }
 
-  PhantomJS._(Future<Process> startBrowser(), this.remoteDebuggerUrl)
+  PhantomJS._(Future<Process> Function() startBrowser, this.remoteDebuggerUrl)
       : super(startBrowser);
 }
diff --git a/pkgs/test/lib/src/runner/browser/platform.dart b/pkgs/test/lib/src/runner/browser/platform.dart
index e46cbb1..a2af0b3 100644
--- a/pkgs/test/lib/src/runner/browser/platform.dart
+++ b/pkgs/test/lib/src/runner/browser/platform.dart
@@ -121,15 +121,15 @@
   ///
   /// This is used to make sure that a given test suite is only compiled once
   /// per run, rather than once per browser per run.
-  final _compileFutures = Map<String, Future>();
+  final _compileFutures = <String, Future>{};
 
   /// Mappers for Dartifying stack traces, indexed by test path.
-  final _mappers = Map<String, StackTraceMapper>();
+  final _mappers = <String, StackTraceMapper>{};
 
   BrowserPlatform._(this._server, Configuration config, String faviconPath,
       {String root})
       : _config = config,
-        _root = root == null ? p.current : root,
+        _root = root ?? p.current,
         _compiledDir = config.pubServeUrl == null ? createTempDir() : null,
         _http = config.pubServeUrl == null ? null : HttpClient() {
     var cascade = shelf.Cascade().add(_webSocketHandler.handler);
@@ -200,13 +200,16 @@
     return shelf.Response.notFound('Not found.');
   }
 
+  @override
   ExecutableSettings parsePlatformSettings(YamlMap settings) =>
       ExecutableSettings.parse(settings);
 
+  @override
   ExecutableSettings mergePlatformSettings(
           ExecutableSettings settings1, ExecutableSettings settings2) =>
       settings1.merge(settings2);
 
+  @override
   void customizePlatform(Runtime runtime, ExecutableSettings settings) {
     var oldSettings =
         _browserSettings[runtime] ?? _browserSettings[runtime.root];
@@ -218,6 +221,7 @@
   ///
   /// This will start a browser to load the suite if one isn't already running.
   /// Throws an [ArgumentError] if `platform.platform` isn't a browser.
+  @override
   Future<RunnerSuite> load(String path, SuitePlatform platform,
       SuiteConfiguration suiteConfig, Object message) async {
     var browser = platform.runtime;
@@ -272,6 +276,7 @@
     return suite;
   }
 
+  @override
   StreamChannel loadChannel(String path, SuitePlatform platform) =>
       throw UnimplementedError();
 
@@ -393,7 +398,7 @@
     var completer = Completer<WebSocketChannel>.sync();
     var path = _webSocketHandler.create(webSocketHandler(completer.complete));
     var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
-    var hostUrl = (_config.pubServeUrl == null ? url : _config.pubServeUrl)
+    var hostUrl = (_config.pubServeUrl ?? url)
         .resolve('packages/test/src/runner/browser/static/index.html')
         .replace(queryParameters: {
       'managerUrl': webSocketUrl.toString(),
@@ -415,6 +420,7 @@
   ///
   /// Note that this doesn't close the server itself. Browser tests can still be
   /// loaded, they'll just spawn new browsers.
+  @override
   Future closeEphemeral() {
     var managers = _browserManagers.values.toList();
     _browserManagers.clear();
@@ -429,6 +435,7 @@
   ///
   /// Returns a [Future] that completes once the server is closed and its
   /// resources have been fully released.
+  @override
   Future close() => _closeMemo.runOnce(() async {
         var futures =
             _browserManagers.values.map<Future<dynamic>>((future) async {
diff --git a/pkgs/test/lib/src/runner/browser/safari.dart b/pkgs/test/lib/src/runner/browser/safari.dart
index b22e0bf..2bd5d80 100644
--- a/pkgs/test/lib/src/runner/browser/safari.dart
+++ b/pkgs/test/lib/src/runner/browser/safari.dart
@@ -20,6 +20,7 @@
 ///
 /// Any errors starting or running the process are reported through [onExit].
 class Safari extends Browser {
+  @override
   final name = 'Safari';
 
   Safari(url, {ExecutableSettings settings})
diff --git a/pkgs/test/lib/src/runner/node/platform.dart b/pkgs/test/lib/src/runner/node/platform.dart
index a24bc1b..c888f93 100644
--- a/pkgs/test/lib/src/runner/node/platform.dart
+++ b/pkgs/test/lib/src/runner/node/platform.dart
@@ -62,22 +62,27 @@
       : _config = Configuration.current,
         _http = Configuration.current.pubServeUrl == null ? null : HttpClient();
 
+  @override
   ExecutableSettings parsePlatformSettings(YamlMap settings) =>
       ExecutableSettings.parse(settings);
 
+  @override
   ExecutableSettings mergePlatformSettings(
           ExecutableSettings settings1, ExecutableSettings settings2) =>
       settings1.merge(settings2);
 
+  @override
   void customizePlatform(Runtime runtime, ExecutableSettings settings) {
     var oldSettings = _settings[runtime] ?? _settings[runtime.root];
     if (oldSettings != null) settings = oldSettings.merge(settings);
     _settings[runtime] = settings;
   }
 
+  @override
   StreamChannel loadChannel(String path, SuitePlatform platform) =>
       throw UnimplementedError();
 
+  @override
   Future<RunnerSuite> load(String path, SuitePlatform platform,
       SuiteConfiguration suiteConfig, Object message) async {
     var pair = await _loadChannel(path, platform.runtime, suiteConfig);
@@ -279,6 +284,7 @@
     }
   }
 
+  @override
   Future close() => _closeMemo.runOnce(() async {
         await _compilers.close();
 
diff --git a/pkgs/test/lib/src/runner/node/socket_channel.dart b/pkgs/test/lib/src/runner/node/socket_channel.dart
index b296a5e..0c2036a 100644
--- a/pkgs/test/lib/src/runner/node/socket_channel.dart
+++ b/pkgs/test/lib/src/runner/node/socket_channel.dart
@@ -22,9 +22,9 @@
 
 @JS()
 class _Socket {
-  external setEncoding(String encoding);
-  external on(String event, void callback(String chunk));
-  external write(String data);
+  external void setEncoding(String encoding);
+  external void on(String event, void Function(String chunk) callback);
+  external void write(String data);
 }
 
 /// Returns a [StreamChannel] of JSON-encodable objects that communicates over a
diff --git a/pkgs/test/lib/src/util/one_off_handler.dart b/pkgs/test/lib/src/util/one_off_handler.dart
index a317072..7667df3 100644
--- a/pkgs/test/lib/src/util/one_off_handler.dart
+++ b/pkgs/test/lib/src/util/one_off_handler.dart
@@ -12,7 +12,7 @@
 /// invalid and don't need to have a persistent URL.
 class OneOffHandler {
   /// A map from URL paths to handlers.
-  final _handlers = Map<String, shelf.Handler>();
+  final _handlers = <String, shelf.Handler>{};
 
   /// The counter of handlers that have been activated.
   var _counter = 0;
diff --git a/pkgs/test/lib/src/util/path_handler.dart b/pkgs/test/lib/src/util/path_handler.dart
index 29f1b98..2fe31c4 100644
--- a/pkgs/test/lib/src/util/path_handler.dart
+++ b/pkgs/test/lib/src/util/path_handler.dart
@@ -58,5 +58,5 @@
 /// A trie node.
 class _Node {
   shelf.Handler handler;
-  final children = Map<String, _Node>();
+  final children = <String, _Node>{};
 }
diff --git a/pkgs/test/mono_pkg.yaml b/pkgs/test/mono_pkg.yaml
index e2c26a6..61ad481 100644
--- a/pkgs/test/mono_pkg.yaml
+++ b/pkgs/test/mono_pkg.yaml
@@ -9,7 +9,7 @@
         dart: dev
       - group:
         - dartanalyzer: --fatal-warnings .
-        dart: 2.2.0
+        dart: 2.3.0
     - unit_test:
       - command: xvfb-run -s "-screen 0 1024x768x24" pub run test --preset travis --total-shards 5 --shard-index 0
       - command: xvfb-run -s "-screen 0 1024x768x24" pub run test --preset travis --total-shards 5 --shard-index 1
diff --git a/pkgs/test/pubspec.yaml b/pkgs/test/pubspec.yaml
index ae0f7d1..31b1f6e 100644
--- a/pkgs/test/pubspec.yaml
+++ b/pkgs/test/pubspec.yaml
@@ -5,7 +5,7 @@
 homepage: https://github.com/dart-lang/test/blob/master/pkgs/test
 
 environment:
-  sdk: '>=2.2.0 <3.0.0'
+  sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
   analyzer: ">=0.36.0 <0.40.0"
diff --git a/pkgs/test/test/common.dart b/pkgs/test/test/common.dart
index 16d897d..ddc1fe5 100644
--- a/pkgs/test/test/common.dart
+++ b/pkgs/test/test/common.dart
@@ -1,3 +1,3 @@
 import 'package:test/test.dart';
 
-myTest(String name, Function() testFn) => test(name, testFn);
+dynamic myTest(String name, Function() testFn) => test(name, testFn);
diff --git a/pkgs/test/test/io.dart b/pkgs/test/test/io.dart
index 22417e6..53e3533 100644
--- a/pkgs/test/test/io.dart
+++ b/pkgs/test/test/io.dart
@@ -76,7 +76,7 @@
   if (reporter != null) allArgs.add('--reporter=$reporter');
   allArgs.addAll(args);
 
-  if (environment == null) environment = {};
+  environment ??= {};
   environment.putIfAbsent('_DART_TEST_TESTING', () => 'true');
 
   return await runDart(allArgs,
@@ -90,11 +90,12 @@
     {Map<String, String> environment,
     String description,
     bool forwardStdio = false}) async {
-  var allArgs = <String>[]
-    ..addAll(Platform.executableArguments.where((arg) =>
-        !arg.startsWith('--package-root=') && !arg.startsWith('--packages=')))
-    ..add(await PackageResolver.current.processArgument)
-    ..addAll(args);
+  var allArgs = <String>[
+    ...Platform.executableArguments.where((arg) =>
+        !arg.startsWith('--package-root=') && !arg.startsWith('--packages=')),
+    await PackageResolver.current.processArgument,
+    ...args
+  ];
 
   return await TestProcess.start(
       p.absolute(Platform.resolvedExecutable), allArgs,
diff --git a/pkgs/test/test/runner/compact_reporter_test.dart b/pkgs/test/test/runner/compact_reporter_test.dart
index 5151946..61a934a 100644
--- a/pkgs/test/test/runner/compact_reporter_test.dart
+++ b/pkgs/test/test/runner/compact_reporter_test.dart
@@ -424,8 +424,8 @@
     }
   ''').create();
 
-  var test =
-      await runTest(['test.dart']..addAll(args ?? []), reporter: 'compact');
+  var test = await runTest(['test.dart', if (args != null) ...args],
+      reporter: 'compact');
   await test.shouldExit();
 
   var stdoutLines = await test.stdout.rest.toList();
diff --git a/pkgs/test/test/runner/expanded_reporter_test.dart b/pkgs/test/test/runner/expanded_reporter_test.dart
index b1458fb..55f2f94 100644
--- a/pkgs/test/test/runner/expanded_reporter_test.dart
+++ b/pkgs/test/test/runner/expanded_reporter_test.dart
@@ -327,7 +327,7 @@
     }
   ''').create();
 
-  var test = await runTest(['test.dart']..addAll(args ?? []));
+  var test = await runTest(['test.dart', if (args != null) ...args]);
   await test.shouldExit();
 
   var stdoutLines = await test.stdoutStream().toList();
diff --git a/pkgs/test/test/runner/hybrid_test.dart b/pkgs/test/test/runner/hybrid_test.dart
index b1d8343..e4f4a77 100644
--- a/pkgs/test/test/runner/hybrid_test.dart
+++ b/pkgs/test/test/runner/hybrid_test.dart
@@ -425,7 +425,7 @@
         }
       ''').create();
 
-    var test = await runTest(['test.dart']..addAll(arguments));
+    var test = await runTest(['test.dart', ...arguments]);
     expect(test.stdout,
         containsInOrder(['+0: hybrid emits numbers', '+1: All tests passed!']));
     await test.shouldExit(0);
@@ -452,7 +452,7 @@
         '''),
     ]).create();
 
-    var test = await runTest(['test/dir/subdir/test.dart']..addAll(arguments));
+    var test = await runTest(['test/dir/subdir/test.dart', ...arguments]);
     expect(test.stdout,
         containsInOrder(['+0: hybrid emits numbers', '+1: All tests passed!']));
     await test.shouldExit(0);
@@ -481,7 +481,7 @@
         '''),
     ]).create();
 
-    var test = await runTest(['test/dir/subdir/test.dart']..addAll(arguments));
+    var test = await runTest(['test/dir/subdir/test.dart', ...arguments]);
     expect(test.stdout,
         containsInOrder(['+0: hybrid emits numbers', '+1: All tests passed!']));
     await test.shouldExit(0);
@@ -508,7 +508,7 @@
         }
       ''').create();
 
-    var test = await runTest(['test.dart']..addAll(arguments));
+    var test = await runTest(['test.dart', ...arguments]);
     expect(test.stdout,
         containsInOrder(['+0: hybrid emits numbers', '+1: All tests passed!']));
     await test.shouldExit(0);
@@ -534,7 +534,7 @@
         }
       ''').create();
 
-    var test = await runTest(['test.dart']..addAll(arguments));
+    var test = await runTest(['test.dart', ...arguments]);
     expect(test.stdout,
         containsInOrder(['+0: hybrid emits numbers', '+1: All tests passed!']));
     await test.shouldExit(0);
@@ -571,7 +571,7 @@
         }
       ''').create();
 
-    var test = await runTest(['test.dart']..addAll(arguments));
+    var test = await runTest(['test.dart', ...arguments]);
     expect(
         test.stdout,
         containsInOrder(
diff --git a/pkgs/test/test/runner/json_reporter_test.dart b/pkgs/test/test/runner/json_reporter_test.dart
index dca4022..77a6fce 100644
--- a/pkgs/test/test/runner/json_reporter_test.dart
+++ b/pkgs/test/test/runner/json_reporter_test.dart
@@ -594,7 +594,7 @@
 
   await d.file('test.dart', testContent.toString()).create();
 
-  var test = await runTest(['test.dart']..addAll(args), reporter: 'json');
+  var test = await runTest(['test.dart', ...args], reporter: 'json');
   await test.shouldExit();
 
   var stdoutLines = await test.stdoutStream().toList();
@@ -605,8 +605,8 @@
 
   // TODO(nweiz): validate each event against the JSON schema when
   // patefacio/json_schema#4 is merged.
-
-  decodeLine(String l) => jsonDecode(l)..remove('time')..remove('stackTrace');
+  dynamic decodeLine(String l) =>
+      jsonDecode(l)..remove('time')..remove('stackTrace');
 
   // Should contain all suites message.
   expect(stdoutLines.map(decodeLine), containsAll([_allSuites()]));
diff --git a/pkgs/test/test/runner/parse_metadata_test.dart b/pkgs/test/test/runner/parse_metadata_test.dart
index ef05e38..635d881 100644
--- a/pkgs/test/test/runner/parse_metadata_test.dart
+++ b/pkgs/test/test/runner/parse_metadata_test.dart
@@ -13,14 +13,14 @@
 
 void main() {
   test('returns empty metadata for an empty file', () {
-    var metadata = parseMetadata(_path, '', Set());
+    var metadata = parseMetadata(_path, '', {});
     expect(metadata.testOn, equals(PlatformSelector.all));
     expect(metadata.timeout.scaleFactor, equals(1));
   });
 
   test('ignores irrelevant annotations', () {
     var metadata =
-        parseMetadata(_path, '@Fblthp\n@Fblthp.foo\nlibrary foo;', Set());
+        parseMetadata(_path, '@Fblthp\n@Fblthp.foo\nlibrary foo;', {});
     expect(metadata.testOn, equals(PlatformSelector.all));
   });
 
@@ -29,21 +29,21 @@
         _path,
         "@foo.TestOn('vm')\n"
         "import 'package:test/test.dart' as foo;",
-        Set());
+        {});
     expect(metadata.testOn.evaluate(SuitePlatform(Runtime.vm)), isTrue);
     expect(metadata.testOn.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
   });
 
   group('@TestOn:', () {
     test('parses a valid annotation', () {
-      var metadata = parseMetadata(_path, "@TestOn('vm')\nlibrary foo;", Set());
+      var metadata = parseMetadata(_path, "@TestOn('vm')\nlibrary foo;", {});
       expect(metadata.testOn.evaluate(SuitePlatform(Runtime.vm)), isTrue);
       expect(metadata.testOn.evaluate(SuitePlatform(Runtime.chrome)), isFalse);
     });
 
     test('ignores a constructor named TestOn', () {
       var metadata =
-          parseMetadata(_path, "@foo.TestOn('foo')\nlibrary foo;", Set());
+          parseMetadata(_path, "@foo.TestOn('foo')\nlibrary foo;", {});
       expect(metadata.testOn, equals(PlatformSelector.all));
     });
 
@@ -51,7 +51,7 @@
       test('multiple @TestOns', () {
         expect(
             () => parseMetadata(
-                _path, "@TestOn('foo')\n@TestOn('bar')\nlibrary foo;", Set()),
+                _path, "@TestOn('foo')\n@TestOn('bar')\nlibrary foo;", {}),
             throwsFormatException);
       });
     });
@@ -59,9 +59,7 @@
 
   group('@Timeout:', () {
     test('parses a valid duration annotation', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout(const Duration(
     hours: 1,
     minutes: 2,
@@ -70,8 +68,7 @@
     microseconds: 5))
 
 library foo;
-''',
-          Set());
+''', {});
       expect(
           metadata.timeout.duration,
           equals(Duration(
@@ -83,9 +80,7 @@
     });
 
     test('parses a valid duration omitting const', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout(Duration(
     hours: 1,
     minutes: 2,
@@ -94,8 +89,7 @@
     microseconds: 5))
 
 library foo;
-''',
-          Set());
+''', {});
       expect(
           metadata.timeout.duration,
           equals(Duration(
@@ -107,9 +101,7 @@
     });
 
     test('parses a valid duration with an import prefix', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout(core.Duration(
     hours: 1,
     minutes: 2,
@@ -117,8 +109,7 @@
     milliseconds: 4,
     microseconds: 5))
 import 'dart:core' as core;
-''',
-          Set());
+''', {});
       expect(
           metadata.timeout.duration,
           equals(Duration(
@@ -130,55 +121,43 @@
     });
 
     test('parses a valid int factor annotation', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout.factor(1)
 
 library foo;
-''',
-          Set());
+''', {});
       expect(metadata.timeout.scaleFactor, equals(1));
     });
 
     test('parses a valid int factor annotation with an import prefix', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @test.Timeout.factor(1)
 import 'package:test/test.dart' as test;
-''',
-          Set());
+''', {});
       expect(metadata.timeout.scaleFactor, equals(1));
     });
 
     test('parses a valid double factor annotation', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout.factor(0.5)
 
 library foo;
-''',
-          Set());
+''', {});
       expect(metadata.timeout.scaleFactor, equals(0.5));
     });
 
     test('parses a valid Timeout.none annotation', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @Timeout.none
 
 library foo;
-''',
-          Set());
+''', {});
       expect(metadata.timeout, same(Timeout.none));
     });
 
     test('ignores a constructor named Timeout', () {
       var metadata =
-          parseMetadata(_path, "@foo.Timeout('foo')\nlibrary foo;", Set());
+          parseMetadata(_path, "@foo.Timeout('foo')\nlibrary foo;", {});
       expect(metadata.timeout.scaleFactor, equals(1));
     });
 
@@ -186,7 +165,7 @@
       test('multiple @Timeouts', () {
         expect(
             () => parseMetadata(_path,
-                '@Timeout.factor(1)\n@Timeout.factor(2)\nlibrary foo;', Set()),
+                '@Timeout.factor(1)\n@Timeout.factor(2)\nlibrary foo;', {}),
             throwsFormatException);
       });
     });
@@ -194,21 +173,19 @@
 
   group('@Skip:', () {
     test('parses a valid annotation', () {
-      var metadata = parseMetadata(_path, '@Skip()\nlibrary foo;', Set());
+      var metadata = parseMetadata(_path, '@Skip()\nlibrary foo;', {});
       expect(metadata.skip, isTrue);
       expect(metadata.skipReason, isNull);
     });
 
     test('parses a valid annotation with a reason', () {
-      var metadata =
-          parseMetadata(_path, "@Skip('reason')\nlibrary foo;", Set());
+      var metadata = parseMetadata(_path, "@Skip('reason')\nlibrary foo;", {});
       expect(metadata.skip, isTrue);
       expect(metadata.skipReason, equals('reason'));
     });
 
     test('ignores a constructor named Skip', () {
-      var metadata =
-          parseMetadata(_path, "@foo.Skip('foo')\nlibrary foo;", Set());
+      var metadata = parseMetadata(_path, "@foo.Skip('foo')\nlibrary foo;", {});
       expect(metadata.skip, isFalse);
     });
 
@@ -216,7 +193,7 @@
       test('multiple @Skips', () {
         expect(
             () => parseMetadata(
-                _path, "@Skip('foo')\n@Skip('bar')\nlibrary foo;", Set()),
+                _path, "@Skip('foo')\n@Skip('bar')\nlibrary foo;", {}),
             throwsFormatException);
       });
     });
@@ -224,13 +201,12 @@
 
   group('@Tags:', () {
     test('parses a valid annotation', () {
-      var metadata = parseMetadata(_path, "@Tags(['a'])\nlibrary foo;", Set());
+      var metadata = parseMetadata(_path, "@Tags(['a'])\nlibrary foo;", {});
       expect(metadata.tags, equals(['a']));
     });
 
     test('ignores a constructor named Tags', () {
-      var metadata =
-          parseMetadata(_path, "@foo.Tags(['a'])\nlibrary foo;", Set());
+      var metadata = parseMetadata(_path, "@foo.Tags(['a'])\nlibrary foo;", {});
       expect(metadata.tags, isEmpty);
     });
 
@@ -238,14 +214,14 @@
       test('multiple @Tags', () {
         expect(
             () => parseMetadata(
-                _path, "@Tags(['a'])\n@Tags(['b'])\nlibrary foo;", Set()),
+                _path, "@Tags(['a'])\n@Tags(['b'])\nlibrary foo;", {}),
             throwsFormatException);
       });
 
       test('String interpolation', () {
         expect(
             () => parseMetadata(
-                _path, "@Tags(['\$a'])\nlibrary foo;\nconst a = 'a';", Set()),
+                _path, "@Tags(['\$a'])\nlibrary foo;\nconst a = 'a';", {}),
             throwsFormatException);
       });
     });
@@ -253,15 +229,12 @@
 
   group('@OnPlatform:', () {
     test('parses a valid annotation', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @OnPlatform({
   'chrome': Timeout.factor(2),
   'vm': [Skip(), Timeout.factor(3)]
 })
-library foo;''',
-          Set());
+library foo;''', {});
 
       var key = metadata.onPlatform.keys.first;
       expect(key.evaluate(SuitePlatform(Runtime.chrome)), isTrue);
@@ -278,16 +251,13 @@
     });
 
     test('parses a valid annotation with an import prefix', () {
-      var metadata = parseMetadata(
-          _path,
-          '''
+      var metadata = parseMetadata(_path, '''
 @test.OnPlatform({
   'chrome': test.Timeout.factor(2),
   'vm': [test.Skip(), test.Timeout.factor(3)]
 })
 import 'package:test/test.dart' as test;
-''',
-          Set());
+''', {});
 
       var key = metadata.onPlatform.keys.first;
       expect(key.evaluate(SuitePlatform(Runtime.chrome)), isTrue);
@@ -305,7 +275,7 @@
 
     test('ignores a constructor named OnPlatform', () {
       var metadata =
-          parseMetadata(_path, "@foo.OnPlatform('foo')\nlibrary foo;", Set());
+          parseMetadata(_path, "@foo.OnPlatform('foo')\nlibrary foo;", {});
       expect(metadata.testOn, equals(PlatformSelector.all));
     });
 
@@ -313,30 +283,28 @@
       test('a map with a unparseable key', () {
         expect(
             () => parseMetadata(
-                _path, "@OnPlatform({'invalid': Skip()})\nlibrary foo;", Set()),
+                _path, "@OnPlatform({'invalid': Skip()})\nlibrary foo;", {}),
             throwsFormatException);
       });
 
       test('a map with an invalid value', () {
         expect(
             () => parseMetadata(_path,
-                "@OnPlatform({'vm': const TestOn('vm')})\nlibrary foo;", Set()),
+                "@OnPlatform({'vm': const TestOn('vm')})\nlibrary foo;", {}),
             throwsFormatException);
       });
 
       test('a map with an invalid value in a list', () {
         expect(
-            () => parseMetadata(
-                _path,
-                "@OnPlatform({'vm': [const TestOn('vm')]})\nlibrary foo;",
-                Set()),
+            () => parseMetadata(_path,
+                "@OnPlatform({'vm': [const TestOn('vm')]})\nlibrary foo;", {}),
             throwsFormatException);
       });
 
       test('multiple @OnPlatforms', () {
         expect(
             () => parseMetadata(
-                _path, '@OnPlatform({})\n@OnPlatform({})\nlibrary foo;', Set()),
+                _path, '@OnPlatform({})\n@OnPlatform({})\nlibrary foo;', {}),
             throwsFormatException);
       });
     });
diff --git a/pkgs/test/test/runner/pub_serve_test.dart b/pkgs/test/test/runner/pub_serve_test.dart
index 0f02f5a..7e5a11b 100644
--- a/pkgs/test/test/runner/pub_serve_test.dart
+++ b/pkgs/test/test/runner/pub_serve_test.dart
@@ -125,7 +125,7 @@
       testWithCompiler('when run on Chrome', (compilerArgs) async {
         await d.dir('web').create();
 
-        var pub = await runPubServe(args: ['web']..addAll(compilerArgs));
+        var pub = await runPubServe(args: ['web', ...compilerArgs]);
         var test = await runTest([_pubServeArg, '-p', 'chrome']);
         expect(
             test.stdout,
@@ -343,7 +343,9 @@
 /// Runs the test described by [testFn] once for each supported compiler on the
 /// current [Platform.version], passing the relevant compiler args for pub serve
 /// as the first argument.
-void testWithCompiler(String name, testFn(List<String> compilerArgs), {tags}) {
+void testWithCompiler(
+    String name, dynamic Function(List<String> compilerArgs) testFn,
+    {tags}) {
   for (var compiler in _compilers) {
     var compilerArgs = ['--web-compiler', compiler];
     test('$name with $compiler', () => testFn(compilerArgs), tags: tags);
diff --git a/pkgs/test/test/runner/test_chain_test.dart b/pkgs/test/test/runner/test_chain_test.dart
index 84dce8d..8c468bf 100644
--- a/pkgs/test/test/runner/test_chain_test.dart
+++ b/pkgs/test/test/runner/test_chain_test.dart
@@ -77,5 +77,5 @@
     var test = await runTest(['test.dart']);
     expect(test.stdoutStream(), emitsThrough(contains('package:test')));
     await test.shouldExit(1);
-  });
+  }, skip: 'https://github.com/dart-lang/test/issues/1120');
 }
diff --git a/pkgs/test/test/util/one_off_handler_test.dart b/pkgs/test/test/util/one_off_handler_test.dart
index 8513ff1..ec97419 100644
--- a/pkgs/test/test/util/one_off_handler_test.dart
+++ b/pkgs/test/test/util/one_off_handler_test.dart
@@ -12,7 +12,8 @@
   OneOffHandler handler;
   setUp(() => handler = OneOffHandler());
 
-  _handle(shelf.Request request) => Future.sync(() => handler.handler(request));
+  Future<shelf.Response> _handle(shelf.Request request) =>
+      Future.sync(() => handler.handler(request));
 
   test('returns a 404 for a root URL', () async {
     var request = shelf.Request('GET', Uri.parse('http://localhost/'));
diff --git a/pkgs/test/test/util/path_handler_test.dart b/pkgs/test/test/util/path_handler_test.dart
index 927cd2a..c4a195f 100644
--- a/pkgs/test/test/util/path_handler_test.dart
+++ b/pkgs/test/test/util/path_handler_test.dart
@@ -12,7 +12,8 @@
   PathHandler handler;
   setUp(() => handler = PathHandler());
 
-  _handle(shelf.Request request) => Future.sync(() => handler.handler(request));
+  Future<shelf.Response> _handle(shelf.Request request) =>
+      Future.sync(() => handler.handler(request));
 
   test('returns a 404 for a root URL', () async {
     var request = shelf.Request('GET', Uri.parse('http://localhost/'));
diff --git a/pkgs/test/test/utils.dart b/pkgs/test/test/utils.dart
index 400fa45..b2a288e 100644
--- a/pkgs/test/test/utils.dart
+++ b/pkgs/test/test/utils.dart
@@ -99,7 +99,7 @@
         .having((e) => e.message, 'message', message);
 
 /// Returns a local [LiveTest] that runs [body].
-LiveTest createTest(body()) {
+LiveTest createTest(dynamic Function() body) {
   var test = LocalTest('test', Metadata(), body);
   var suite = Suite(Group.root([test]), suitePlatform);
   return test.load(suite);
@@ -108,7 +108,7 @@
 /// Runs [body] as a test.
 ///
 /// Once it completes, returns the [LiveTest] used to run it.
-Future<LiveTest> runTestBody(body()) async {
+Future<LiveTest> runTestBody(dynamic Function() body) async {
   var liveTest = createTest(body);
   await liveTest.run();
   return liveTest;
@@ -144,7 +144,8 @@
 /// is called at some later time.
 ///
 /// [stopBlocking] is passed the return value of [test].
-Future expectTestBlocks(test(), stopBlocking(value)) async {
+Future expectTestBlocks(
+    dynamic Function() test, dynamic Function(dynamic) stopBlocking) async {
   LiveTest liveTest;
   Future future;
   liveTest = createTest(() {
@@ -167,7 +168,7 @@
 ///
 /// This is typically used to run multiple tests where later tests make
 /// assertions about the results of previous ones.
-Future expectTestsPass(void body()) async {
+Future expectTestsPass(void Function() body) async {
   var engine = declareEngine(body);
   var success = await engine.run();
 
@@ -179,13 +180,14 @@
 }
 
 /// Runs [body] with a declarer and returns the declared entries.
-List<GroupEntry> declare(void body()) {
+List<GroupEntry> declare(void Function() body) {
   var declarer = Declarer()..declare(body);
   return declarer.build().entries;
 }
 
 /// Runs [body] with a declarer and returns an engine that runs those tests.
-Engine declareEngine(void body(), {bool runSkipped = false, String coverage}) {
+Engine declareEngine(void Function() body,
+    {bool runSkipped = false, String coverage}) {
   var declarer = Declarer()..declare(body);
   return Engine.withSuites([
     RunnerSuite(
diff --git a/pkgs/test/tool/host.dart b/pkgs/test/tool/host.dart
index 713e28d..c1b229c 100644
--- a/pkgs/test/tool/host.dart
+++ b/pkgs/test/tool/host.dart
@@ -38,7 +38,8 @@
   /// running.
   external Function get restartCurrent;
 
-  external factory _JSApi({void resume(), void restartCurrent()});
+  external factory _JSApi(
+      {void Function() resume, void Function() restartCurrent});
 }
 
 /// Sets the top-level `dartTest` object so that it's visible to JS.
@@ -46,10 +47,10 @@
 external set _jsApi(_JSApi api);
 
 /// The iframes created for each loaded test suite, indexed by the suite id.
-final _iframes = Map<int, IFrameElement>();
+final _iframes = <int, IFrameElement>{};
 
 /// Subscriptions created for each loaded test suite, indexed by the suite id.
-final _subscriptions = Map<int, List<StreamSubscription>>();
+final _subscriptions = <int, List<StreamSubscription>>{};
 
 /// The URL for the current page.
 final _currentUrl = Uri.parse(window.location.href);
diff --git a/pkgs/test_api/lib/src/backend/closed_exception.dart b/pkgs/test_api/lib/src/backend/closed_exception.dart
index f2c269b..08a45a0 100644
--- a/pkgs/test_api/lib/src/backend/closed_exception.dart
+++ b/pkgs/test_api/lib/src/backend/closed_exception.dart
@@ -7,5 +7,6 @@
 class ClosedException implements Exception {
   ClosedException();
 
+  @override
   String toString() => 'This test has been closed.';
 }
diff --git a/pkgs/test_api/lib/src/backend/declarer.dart b/pkgs/test_api/lib/src/backend/declarer.dart
index 4a94bc8..60b1b33 100644
--- a/pkgs/test_api/lib/src/backend/declarer.dart
+++ b/pkgs/test_api/lib/src/backend/declarer.dart
@@ -50,13 +50,13 @@
   final bool _noRetry;
 
   /// The set-up functions to run for each test in this group.
-  final _setUps = List<Function()>();
+  final _setUps = <dynamic Function()>[];
 
   /// The tear-down functions to run for each test in this group.
-  final _tearDowns = List<Function()>();
+  final _tearDowns = <dynamic Function()>[];
 
   /// The set-up functions to run once for this group.
-  final _setUpAlls = List<Function()>();
+  final _setUpAlls = <dynamic Function()>[];
 
   /// The default timeout for synthetic tests.
   final _timeout = Timeout(Duration(minutes: 12));
@@ -69,7 +69,7 @@
   Trace _setUpAllTrace;
 
   /// The tear-down functions to run once for this group.
-  final _tearDownAlls = List<Function()>();
+  final _tearDownAlls = <Function()>[];
 
   /// The trace for the first call to [tearDownAll].
   ///
@@ -78,13 +78,13 @@
   Trace _tearDownAllTrace;
 
   /// The children of this group, either tests or sub-groups.
-  final _entries = List<GroupEntry>();
+  final _entries = <GroupEntry>[];
 
   /// Whether [build] has been called for this declarer.
   bool _built = false;
 
   /// The tests and/or groups that have been flagged as solo.
-  final _soloEntries = Set<GroupEntry>();
+  final _soloEntries = <GroupEntry>[];
 
   /// Whether any tests and/or groups have been flagged as solo.
   bool get _solo => _soloEntries.isNotEmpty;
@@ -127,10 +127,11 @@
   /// Runs [body] with this declarer as [Declarer.current].
   ///
   /// Returns the return value of [body].
-  declare(body()) => runZoned(body, zoneValues: {#test.declarer: this});
+  void declare(void Function() body) =>
+      runZoned(body, zoneValues: {#test.declarer: this});
 
   /// Defines a test case with the given name and body.
-  void test(String name, body(),
+  void test(String name, dynamic Function() body,
       {String testOn,
       Timeout timeout,
       skip,
@@ -181,7 +182,7 @@
   }
 
   /// Creates a group of tests.
-  void group(String name, void body(),
+  void group(String name, void Function() body,
       {String testOn,
       Timeout timeout,
       skip,
@@ -222,26 +223,26 @@
   String _prefix(String name) => _name == null ? name : '$_name $name';
 
   /// Registers a function to be run before each test in this group.
-  void setUp(callback()) {
+  void setUp(dynamic Function() callback) {
     _checkNotBuilt('setUp');
     _setUps.add(callback);
   }
 
   /// Registers a function to be run after each test in this group.
-  void tearDown(callback()) {
+  void tearDown(dynamic Function() callback) {
     _checkNotBuilt('tearDown');
     _tearDowns.add(callback);
   }
 
   /// Registers a function to be run once before all tests.
-  void setUpAll(callback()) {
+  void setUpAll(dynamic Function() callback) {
     _checkNotBuilt('setUpAll');
     if (_collectTraces) _setUpAllTrace ??= Trace.current(2);
     _setUpAlls.add(callback);
   }
 
   /// Registers a function to be run once after all tests.
-  void tearDownAll(callback()) {
+  void tearDownAll(dynamic Function() callback) {
     _checkNotBuilt('tearDownAll');
     if (_collectTraces) _tearDownAllTrace ??= Trace.current(2);
     _tearDownAlls.add(callback);
@@ -249,7 +250,8 @@
 
   /// Like [tearDownAll], but called from within a running [setUpAll] test to
   /// dynamically add a [tearDownAll].
-  void addTearDownAll(callback()) => _tearDownAlls.add(callback);
+  void addTearDownAll(dynamic Function() callback) =>
+      _tearDownAlls.add(callback);
 
   /// Finalizes and returns the group being declared.
   ///
diff --git a/pkgs/test_api/lib/src/backend/group.dart b/pkgs/test_api/lib/src/backend/group.dart
index 3f831f0..30f5238 100644
--- a/pkgs/test_api/lib/src/backend/group.dart
+++ b/pkgs/test_api/lib/src/backend/group.dart
@@ -13,10 +13,13 @@
 ///
 /// It includes metadata that applies to all contained tests.
 class Group implements GroupEntry {
+  @override
   final String name;
 
+  @override
   final Metadata metadata;
 
+  @override
   final Trace trace;
 
   /// The children of this group.
@@ -49,8 +52,9 @@
   Group(this.name, Iterable<GroupEntry> entries,
       {Metadata metadata, this.trace, this.setUpAll, this.tearDownAll})
       : entries = List<GroupEntry>.unmodifiable(entries),
-        metadata = metadata == null ? Metadata() : metadata;
+        metadata = metadata ?? Metadata();
 
+  @override
   Group forPlatform(SuitePlatform platform) {
     if (!metadata.testOn.evaluate(platform)) return null;
     var newMetadata = metadata.forPlatform(platform);
@@ -63,7 +67,8 @@
         tearDownAll: tearDownAll);
   }
 
-  Group filter(bool callback(Test test)) {
+  @override
+  Group filter(bool Function(Test) callback) {
     var filtered = _map((entry) => entry.filter(callback));
     if (filtered.isEmpty && entries.isNotEmpty) return null;
     return Group(name, filtered,
@@ -76,7 +81,7 @@
   /// Returns the entries of this group mapped using [callback].
   ///
   /// Any `null` values returned by [callback] will be removed.
-  List<GroupEntry> _map(GroupEntry callback(GroupEntry entry)) {
+  List<GroupEntry> _map(GroupEntry Function(GroupEntry) callback) {
     return entries
         .map((entry) => callback(entry))
         .where((entry) => entry != null)
diff --git a/pkgs/test_api/lib/src/backend/group_entry.dart b/pkgs/test_api/lib/src/backend/group_entry.dart
index 2d2a341..44b3054 100644
--- a/pkgs/test_api/lib/src/backend/group_entry.dart
+++ b/pkgs/test_api/lib/src/backend/group_entry.dart
@@ -35,5 +35,5 @@
   ///
   /// Returns `null` if this is a test that doesn't match [callback] or a group
   /// where no child tests match [callback].
-  GroupEntry filter(bool callback(Test test));
+  GroupEntry filter(bool Function(Test) callback);
 }
diff --git a/pkgs/test_api/lib/src/backend/invoker.dart b/pkgs/test_api/lib/src/backend/invoker.dart
index 837efb0..08009b1 100644
--- a/pkgs/test_api/lib/src/backend/invoker.dart
+++ b/pkgs/test_api/lib/src/backend/invoker.dart
@@ -24,8 +24,11 @@
 
 /// A test in this isolate.
 class LocalTest extends Test {
+  @override
   final String name;
+  @override
   final Metadata metadata;
+  @override
   final Trace trace;
 
   /// Whether this is a test defined using `setUpAll()` or `tearDownAll()`.
@@ -51,11 +54,13 @@
       this.isScaffoldAll);
 
   /// Loads a single runnable instance of this test.
+  @override
   LiveTest load(Suite suite, {Iterable<Group> groups}) {
     var invoker = Invoker._(suite, this, groups: groups, guarded: _guarded);
     return invoker.liveTest;
   }
 
+  @override
   Test forPlatform(SuitePlatform platform) {
     if (!metadata.testOn.evaluate(platform)) return null;
     return LocalTest._(name, metadata.forPlatform(platform), _body, trace,
@@ -140,7 +145,7 @@
 
   /// Runs [callback] in a zone where unhandled errors from [LiveTest]s are
   /// caught and dispatched to the appropriate [Invoker].
-  static T guard<T>(T callback()) =>
+  static T guard<T>(T Function() callback) =>
       runZoned(callback, zoneSpecification: ZoneSpecification(
           // Use [handleUncaughtError] rather than [onError] so we can
           // capture [zone] and with it the outstanding callback counter for
@@ -183,7 +188,7 @@
   ///
   /// The [callback] may return a [Future]. Like all tear-downs, callbacks are
   /// run in the reverse of the order they're declared.
-  void addTearDown(callback()) {
+  void addTearDown(dynamic Function() callback) {
     if (closed) throw ClosedException();
 
     if (_test.isScaffoldAll) {
diff --git a/pkgs/test_api/lib/src/backend/live_test_controller.dart b/pkgs/test_api/lib/src/backend/live_test_controller.dart
index 00461ec..0aad846 100644
--- a/pkgs/test_api/lib/src/backend/live_test_controller.dart
+++ b/pkgs/test_api/lib/src/backend/live_test_controller.dart
@@ -18,27 +18,38 @@
 class _LiveTest extends LiveTest {
   final LiveTestController _controller;
 
+  @override
   Suite get suite => _controller._suite;
 
+  @override
   List<Group> get groups => _controller._groups;
 
+  @override
   Test get test => _controller._test;
 
+  @override
   State get state => _controller._state;
 
+  @override
   Stream<State> get onStateChange =>
       _controller._onStateChangeController.stream;
 
+  @override
   List<AsyncError> get errors => UnmodifiableListView(_controller._errors);
 
+  @override
   Stream<AsyncError> get onError => _controller._onErrorController.stream;
 
+  @override
   Stream<Message> get onMessage => _controller._onMessageController.stream;
 
+  @override
   Future<void> get onComplete => _controller.onComplete;
 
+  @override
   Future<void> run() => _controller._run();
 
+  @override
   Future<void> close() => _controller._close();
 
   _LiveTest(this._controller);
@@ -76,7 +87,7 @@
   final Function _onClose;
 
   /// The list of errors caught by the test.
-  final _errors = List<AsyncError>();
+  final _errors = <AsyncError>[];
 
   /// The current state of the test.
   var _state = const State(Status.pending, Result.success);
@@ -125,7 +136,8 @@
   ///
   /// If [groups] is passed, it's used to populate the list of groups that
   /// contain this test. Otherwise, `suite.group` is used.
-  LiveTestController(Suite suite, this._test, void onRun(), void onClose(),
+  LiveTestController(
+      Suite suite, this._test, void Function() onRun, void Function() onClose,
       {Iterable<Group> groups})
       : _suite = suite,
         _onRun = onRun,
diff --git a/pkgs/test_api/lib/src/backend/message.dart b/pkgs/test_api/lib/src/backend/message.dart
index c2cfa66..efe152f 100644
--- a/pkgs/test_api/lib/src/backend/message.dart
+++ b/pkgs/test_api/lib/src/backend/message.dart
@@ -41,5 +41,6 @@
 
   const MessageType._(this.name);
 
+  @override
   String toString() => name;
 }
diff --git a/pkgs/test_api/lib/src/backend/metadata.dart b/pkgs/test_api/lib/src/backend/metadata.dart
index a3b097c..58e4f5a 100644
--- a/pkgs/test_api/lib/src/backend/metadata.dart
+++ b/pkgs/test_api/lib/src/backend/metadata.dart
@@ -100,7 +100,7 @@
                 '"$platform".');
           }
 
-          skip = metadatum.reason == null ? true : metadatum.reason;
+          skip = metadatum.reason ?? true;
         } else {
           throw ArgumentError('Metadata for platform "$platform" must be a '
               'Timeout, Skip, or List of those; was "$metadata".');
@@ -116,8 +116,8 @@
   ///
   /// Throws an [ArgumentError] if [tags] is not a [String] or an [Iterable].
   static Set<String> _parseTags(tags) {
-    if (tags == null) return Set();
-    if (tags is String) return Set.from([tags]);
+    if (tags == null) return {};
+    if (tags is String) return {tags};
     if (tags is! Iterable) {
       throw ArgumentError.value(
           tags, 'tags', 'must be either a String or an Iterable.');
@@ -149,7 +149,7 @@
       Map<PlatformSelector, Metadata> onPlatform,
       Map<BooleanSelector, Metadata> forTag}) {
     // Returns metadata without forTag resolved at all.
-    _unresolved() => Metadata._(
+    Metadata _unresolved() => Metadata._(
         testOn: testOn,
         timeout: timeout,
         skip: skip,
@@ -194,13 +194,13 @@
       Iterable<String> tags,
       Map<PlatformSelector, Metadata> onPlatform,
       Map<BooleanSelector, Metadata> forTag})
-      : testOn = testOn == null ? PlatformSelector.all : testOn,
-        timeout = timeout == null ? const Timeout.factor(1) : timeout,
+      : testOn = testOn ?? PlatformSelector.all,
+        timeout = timeout ?? const Timeout.factor(1),
         _skip = skip,
         _verboseTrace = verboseTrace,
         _chainStackTraces = chainStackTraces,
         _retry = retry,
-        tags = UnmodifiableSetView(tags == null ? Set() : tags.toSet()),
+        tags = UnmodifiableSetView(tags == null ? {} : tags.toSet()),
         onPlatform =
             onPlatform == null ? const {} : UnmodifiableMapView(onPlatform),
         forTag = forTag == null ? const {} : UnmodifiableMapView(forTag) {
@@ -224,7 +224,7 @@
       : testOn = testOn == null
             ? PlatformSelector.all
             : PlatformSelector.parse(testOn),
-        timeout = timeout == null ? const Timeout.factor(1) : timeout,
+        timeout = timeout ?? const Timeout.factor(1),
         _skip = skip == null ? null : skip != false,
         _verboseTrace = verboseTrace,
         _chainStackTraces = chainStackTraces,
@@ -254,9 +254,11 @@
         _chainStackTraces = serialized['chainStackTraces'] as bool,
         _retry = serialized['retry'] as int,
         tags = Set.from(serialized['tags'] as Iterable),
-        onPlatform = Map.fromIterable(serialized['onPlatform'] as Iterable,
-            key: (pair) => PlatformSelector.parse(pair.first as String),
-            value: (pair) => Metadata.deserialize(pair.last)),
+        onPlatform = {
+          for (var pair in serialized['onPlatform'])
+            PlatformSelector.parse(pair.first as String):
+                Metadata.deserialize(pair.last)
+        },
         forTag = (serialized['forTag'] as Map).map((key, nested) => MapEntry(
             BooleanSelector.parse(key as String),
             Metadata.deserialize(nested)));
@@ -328,10 +330,10 @@
       Map<BooleanSelector, Metadata> forTag}) {
     testOn ??= this.testOn;
     timeout ??= this.timeout;
-    skip ??= this._skip;
-    verboseTrace ??= this._verboseTrace;
-    chainStackTraces ??= this._chainStackTraces;
-    retry ??= this._retry;
+    skip ??= _skip;
+    verboseTrace ??= _verboseTrace;
+    chainStackTraces ??= _chainStackTraces;
+    retry ??= _retry;
     skipReason ??= this.skipReason;
     onPlatform ??= this.onPlatform;
     tags ??= this.tags;
@@ -364,7 +366,7 @@
 
   /// Serializes [this] into a JSON-safe object that can be deserialized using
   /// [new Metadata.deserialize].
-  serialize() {
+  Map<String, dynamic> serialize() {
     // Make this a list to guarantee that the order is preserved.
     var serializedOnPlatform = [];
     onPlatform.forEach((key, value) {
@@ -387,7 +389,7 @@
   }
 
   /// Serializes timeout into a JSON-safe object.
-  _serializeTimeout(Timeout timeout) {
+  dynamic _serializeTimeout(Timeout timeout) {
     if (timeout == Timeout.none) return 'none';
     return {
       'duration':
diff --git a/pkgs/test_api/lib/src/backend/operating_system.dart b/pkgs/test_api/lib/src/backend/operating_system.dart
index 7e99895..f2b7639 100644
--- a/pkgs/test_api/lib/src/backend/operating_system.dart
+++ b/pkgs/test_api/lib/src/backend/operating_system.dart
@@ -77,5 +77,6 @@
 
   const OperatingSystem._(this.name, this.identifier);
 
+  @override
   String toString() => name;
 }
diff --git a/pkgs/test_api/lib/src/backend/platform_selector.dart b/pkgs/test_api/lib/src/backend/platform_selector.dart
index 96a3d1c..f2ab5a9 100644
--- a/pkgs/test_api/lib/src/backend/platform_selector.dart
+++ b/pkgs/test_api/lib/src/backend/platform_selector.dart
@@ -10,10 +10,16 @@
 import 'suite_platform.dart';
 
 /// The set of variable names that are valid for all platform selectors.
-final _universalValidVariables =
-    Set<String>.from(['posix', 'dart-vm', 'browser', 'js', 'blink', 'google'])
-      ..addAll(Runtime.builtIn.map((runtime) => runtime.identifier))
-      ..addAll(OperatingSystem.all.map((os) => os.identifier));
+final _universalValidVariables = {
+  'posix',
+  'dart-vm',
+  'browser',
+  'js',
+  'blink',
+  'google',
+  for (var runtime in Runtime.builtIn) runtime.identifier,
+  for (var os in OperatingSystem.all) os.identifier,
+};
 
 /// An expression for selecting certain platforms, including operating systems
 /// and browsers.
@@ -46,7 +52,7 @@
   /// [SourceSpanFormatException] using [span].
   ///
   /// If [span] is `null`, runs [body] as-is.
-  static T _wrapFormatException<T>(T body(), SourceSpan span) {
+  static T _wrapFormatException<T>(T Function() body, SourceSpan span) {
     if (span == null) return body();
 
     try {
@@ -103,10 +109,13 @@
     return PlatformSelector._(_inner.intersection(other._inner));
   }
 
+  @override
   String toString() => _inner.toString();
 
+  @override
   bool operator ==(other) =>
       other is PlatformSelector && _inner == other._inner;
 
+  @override
   int get hashCode => _inner.hashCode;
 }
diff --git a/pkgs/test_api/lib/src/backend/runtime.dart b/pkgs/test_api/lib/src/backend/runtime.dart
index 9b3f9d9..bbd24db 100644
--- a/pkgs/test_api/lib/src/backend/runtime.dart
+++ b/pkgs/test_api/lib/src/backend/runtime.dart
@@ -153,5 +153,6 @@
     throw StateError('A child platform may not be extended.');
   }
 
+  @override
   String toString() => name;
 }
diff --git a/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart b/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
index 62d5243..2bb897e 100644
--- a/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
+++ b/pkgs/test_api/lib/src/backend/stack_trace_formatter.dart
@@ -22,12 +22,12 @@
   /// as-is.
   StackTraceMapper _mapper;
 
-  /// The list of packages to fold when producing terse [Chain]s.
-  var _except = Set<String>.from(['test', 'stream_channel', 'test_api']);
+  /// The set of packages to fold when producing terse [Chain]s.
+  var _except = {'test', 'stream_channel', 'test_api'};
 
   /// If non-empty, all packages not in this list will be folded when producing
   /// terse [Chain]s.
-  var _only = Set<String>();
+  var _only = <String>{};
 
   /// Returns the current manager, or `null` if this isn't called within a call
   /// to [asCurrent].
@@ -38,7 +38,8 @@
   ///
   /// This is zone-scoped, so [this] will be the current configuration in any
   /// asynchronous callbacks transitively created by [body].
-  T asCurrent<T>(T body()) => runZoned(body, zoneValues: {_currentKey: this});
+  T asCurrent<T>(T Function() body) =>
+      runZoned(body, zoneValues: {_currentKey: this});
 
   /// Configure how stack traces are formatted.
   ///
diff --git a/pkgs/test_api/lib/src/backend/state.dart b/pkgs/test_api/lib/src/backend/state.dart
index afbde7d..ba82cd0 100644
--- a/pkgs/test_api/lib/src/backend/state.dart
+++ b/pkgs/test_api/lib/src/backend/state.dart
@@ -27,11 +27,14 @@
 
   const State(this.status, this.result);
 
+  @override
   bool operator ==(other) =>
       other is State && status == other.status && result == other.result;
 
+  @override
   int get hashCode => status.hashCode ^ (7 * result.hashCode);
 
+  @override
   String toString() {
     if (status == Status.pending) return 'pending';
     if (status == Status.complete) return result.toString();
@@ -75,6 +78,7 @@
 
   const Status._(this.name);
 
+  @override
   String toString() => name;
 }
 
@@ -134,5 +138,6 @@
 
   const Result._(this.name);
 
+  @override
   String toString() => name;
 }
diff --git a/pkgs/test_api/lib/src/backend/suite.dart b/pkgs/test_api/lib/src/backend/suite.dart
index 2a1a13f..695d305 100644
--- a/pkgs/test_api/lib/src/backend/suite.dart
+++ b/pkgs/test_api/lib/src/backend/suite.dart
@@ -48,9 +48,9 @@
   ///
   /// Unlike [GroupEntry.filter], this never returns `null`. If all entries are
   /// filtered out, it returns an empty suite.
-  Suite filter(bool callback(Test test)) {
+  Suite filter(bool Function(Test) callback) {
     var filtered = group.filter(callback);
-    if (filtered == null) filtered = Group.root([], metadata: metadata);
+    filtered ??= Group.root([], metadata: metadata);
     return Suite(filtered, platform, path: path);
   }
 
diff --git a/pkgs/test_api/lib/src/backend/test.dart b/pkgs/test_api/lib/src/backend/test.dart
index 07df8c3..870f5e1 100644
--- a/pkgs/test_api/lib/src/backend/test.dart
+++ b/pkgs/test_api/lib/src/backend/test.dart
@@ -17,10 +17,13 @@
 /// directly. To run one, load a live version using [Test.load] and run it using
 /// [LiveTest.run].
 abstract class Test implements GroupEntry {
+  @override
   String get name;
 
+  @override
   Metadata get metadata;
 
+  @override
   Trace get trace;
 
   /// Loads a live version of this test, which can be used to run it a single
@@ -31,7 +34,9 @@
   /// defaults to just containing `suite.group`.
   LiveTest load(Suite suite, {Iterable<Group> groups});
 
+  @override
   Test forPlatform(SuitePlatform platform);
 
-  Test filter(bool callback(Test test)) => callback(this) ? this : null;
+  @override
+  Test filter(bool Function(Test) callback) => callback(this) ? this : null;
 }
diff --git a/pkgs/test_api/lib/src/frontend/async_matcher.dart b/pkgs/test_api/lib/src/frontend/async_matcher.dart
index d797850..e956aec 100644
--- a/pkgs/test_api/lib/src/frontend/async_matcher.dart
+++ b/pkgs/test_api/lib/src/frontend/async_matcher.dart
@@ -27,8 +27,9 @@
   ///
   /// If this returns a [String] synchronously, [expect] will synchronously
   /// throw a [TestFailure] and [matches] will synchronusly return `false`.
-  /*FutureOr<String>*/ matchAsync(item);
+  dynamic /*FutureOr<String>*/ matchAsync(item);
 
+  @override
   bool matches(item, Map matchState) {
     var result = matchAsync(item);
     expect(result,
@@ -51,6 +52,7 @@
     return true;
   }
 
+  @override
   Description describeMismatch(
           item, Description description, Map matchState, bool verbose) =>
       StringDescription(matchState[this] as String);
diff --git a/pkgs/test_api/lib/src/frontend/expect.dart b/pkgs/test_api/lib/src/frontend/expect.dart
index 37567b5..b69dc2f 100644
--- a/pkgs/test_api/lib/src/frontend/expect.dart
+++ b/pkgs/test_api/lib/src/frontend/expect.dart
@@ -18,6 +18,7 @@
 
   TestFailure(this.message);
 
+  @override
   String toString() => message;
 }
 
diff --git a/pkgs/test_api/lib/src/frontend/expect_async.dart b/pkgs/test_api/lib/src/frontend/expect_async.dart
index 69cf030..42b618d 100644
--- a/pkgs/test_api/lib/src/frontend/expect_async.dart
+++ b/pkgs/test_api/lib/src/frontend/expect_async.dart
@@ -91,15 +91,15 @@
   /// as a reason it's expected to be called. If [isDone] is passed, the test
   /// won't be allowed to complete until it returns `true`.
   _ExpectedFunction(Function callback, int minExpected, int maxExpected,
-      {String id, String reason, bool isDone()})
-      : this._callback = callback,
+      {String id, String reason, bool Function() isDone})
+      : _callback = callback,
         _minExpectedCalls = minExpected,
         _maxExpectedCalls =
             (maxExpected == 0 && minExpected > 0) ? minExpected : maxExpected,
-        this._isDone = isDone,
-        this._reason = reason == null ? '' : '\n$reason',
-        this._zone = Zone.current,
-        this._id = _makeCallbackId(id, callback) {
+        _isDone = isDone,
+        _reason = reason == null ? '' : '\n$reason',
+        _zone = Zone.current,
+        _id = _makeCallbackId(id, callback) {
     if (_invoker == null) {
       throw StateError('[expectAsync] was called outside of a test.');
     } else if (maxExpected > 0 && minExpected > maxExpected) {
@@ -258,7 +258,7 @@
 /// This method takes callbacks with zero arguments. See also
 /// [expectAsync1], [expectAsync2], [expectAsync3], [expectAsync4],
 /// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func0<T> expectAsync0<T>(T callback(),
+Func0<T> expectAsync0<T>(T Function() callback,
     {int count = 1, int max = 0, String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsync0() may only be called within a test.');
@@ -289,7 +289,7 @@
 /// This method takes callbacks with one argument. See also
 /// [expectAsync0], [expectAsync2], [expectAsync3], [expectAsync4],
 /// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func1<T, A> expectAsync1<T, A>(T callback(A a),
+Func1<T, A> expectAsync1<T, A>(T Function(A) callback,
     {int count = 1, int max = 0, String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsync1() may only be called within a test.');
@@ -320,7 +320,7 @@
 /// This method takes callbacks with two arguments. See also
 /// [expectAsync0], [expectAsync1], [expectAsync3], [expectAsync4],
 /// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func2<T, A, B> expectAsync2<T, A, B>(T callback(A a, B b),
+Func2<T, A, B> expectAsync2<T, A, B>(T Function(A, B) callback,
     {int count = 1, int max = 0, String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsync2() may only be called within a test.');
@@ -351,7 +351,7 @@
 /// This method takes callbacks with three arguments. See also
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync4],
 /// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func3<T, A, B, C> expectAsync3<T, A, B, C>(T callback(A a, B b, C c),
+Func3<T, A, B, C> expectAsync3<T, A, B, C>(T Function(A, B, C) callback,
     {int count = 1, int max = 0, String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsync3() may only be called within a test.');
@@ -382,8 +382,12 @@
 /// This method takes callbacks with four arguments. See also
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
 /// [expectAsync5], and [expectAsync6] for callbacks with different arity.
-Func4<T, A, B, C, D> expectAsync4<T, A, B, C, D>(T callback(A a, B b, C c, D d),
-    {int count = 1, int max = 0, String id, String reason}) {
+Func4<T, A, B, C, D> expectAsync4<T, A, B, C, D>(
+    T Function(A, B, C, D) callback,
+    {int count = 1,
+    int max = 0,
+    String id,
+    String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsync4() may only be called within a test.');
   }
@@ -414,7 +418,7 @@
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
 /// [expectAsync4], and [expectAsync6] for callbacks with different arity.
 Func5<T, A, B, C, D, E> expectAsync5<T, A, B, C, D, E>(
-    T callback(A a, B b, C c, D d, E e),
+    T Function(A, B, C, D, E) callback,
     {int count = 1,
     int max = 0,
     String id,
@@ -449,7 +453,7 @@
 /// [expectAsync0], [expectAsync1], [expectAsync2], [expectAsync3],
 /// [expectAsync4], and [expectAsync5] for callbacks with different arity.
 Func6<T, A, B, C, D, E, F> expectAsync6<T, A, B, C, D, E, F>(
-    T callback(A a, B b, C c, D d, E e, F f),
+    T Function(A, B, C, D, E, F) callback,
     {int count = 1,
     int max = 0,
     String id,
@@ -467,7 +471,7 @@
 /// [expectAsyncUntil2], [expectAsyncUntil3], [expectAsyncUntil4],
 /// [expectAsyncUntil5], or [expectAsyncUntil6] instead.
 @Deprecated('Will be removed in 0.13.0')
-Function expectAsyncUntil(Function callback, bool isDone(),
+Function expectAsyncUntil(Function callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil() may only be called within a test.');
@@ -495,7 +499,7 @@
 /// [expectAsyncUntil1], [expectAsyncUntil2], [expectAsyncUntil3],
 /// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
 /// callbacks with different arity.
-Func0<T> expectAsyncUntil0<T>(T callback(), bool isDone(),
+Func0<T> expectAsyncUntil0<T>(T Function() callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil0() may only be called within a test.');
@@ -523,7 +527,8 @@
 /// [expectAsyncUntil0], [expectAsyncUntil2], [expectAsyncUntil3],
 /// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
 /// callbacks with different arity.
-Func1<T, A> expectAsyncUntil1<T, A>(T callback(A a), bool isDone(),
+Func1<T, A> expectAsyncUntil1<T, A>(
+    T Function(A) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil1() may only be called within a test.');
@@ -551,7 +556,8 @@
 /// [expectAsyncUntil0], [expectAsyncUntil1], [expectAsyncUntil3],
 /// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
 /// callbacks with different arity.
-Func2<T, A, B> expectAsyncUntil2<T, A, B>(T callback(A a, B b), bool isDone(),
+Func2<T, A, B> expectAsyncUntil2<T, A, B>(
+    T Function(A, B) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil2() may only be called within a test.');
@@ -580,7 +586,7 @@
 /// [expectAsyncUntil4], [expectAsyncUntil5], and [expectAsyncUntil6] for
 /// callbacks with different arity.
 Func3<T, A, B, C> expectAsyncUntil3<T, A, B, C>(
-    T callback(A a, B b, C c), bool isDone(),
+    T Function(A, B, C) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil3() may only be called within a test.');
@@ -609,7 +615,7 @@
 /// [expectAsyncUntil3], [expectAsyncUntil5], and [expectAsyncUntil6] for
 /// callbacks with different arity.
 Func4<T, A, B, C, D> expectAsyncUntil4<T, A, B, C, D>(
-    T callback(A a, B b, C c, D d), bool isDone(),
+    T Function(A, B, C, D) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil4() may only be called within a test.');
@@ -638,7 +644,7 @@
 /// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil6] for
 /// callbacks with different arity.
 Func5<T, A, B, C, D, E> expectAsyncUntil5<T, A, B, C, D, E>(
-    T callback(A a, B b, C c, D d, E e), bool isDone(),
+    T Function(A, B, C, D, E) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil5() may only be called within a test.');
@@ -667,7 +673,7 @@
 /// [expectAsyncUntil3], [expectAsyncUntil4], and [expectAsyncUntil5] for
 /// callbacks with different arity.
 Func6<T, A, B, C, D, E, F> expectAsyncUntil6<T, A, B, C, D, E, F>(
-    T callback(A a, B b, C c, D d, E e, F f), bool isDone(),
+    T Function(A, B, C, D, E, F) callback, bool Function() isDone,
     {String id, String reason}) {
   if (Invoker.current == null) {
     throw StateError('expectAsyncUntil() may only be called within a test.');
diff --git a/pkgs/test_api/lib/src/frontend/future_matchers.dart b/pkgs/test_api/lib/src/frontend/future_matchers.dart
index 2fa4af0..8117395 100644
--- a/pkgs/test_api/lib/src/frontend/future_matchers.dart
+++ b/pkgs/test_api/lib/src/frontend/future_matchers.dart
@@ -45,7 +45,8 @@
   const _Completes(this._matcher);
 
   // Avoid async/await so we synchronously start listening to [item].
-  /*FutureOr<String>*/ matchAsync(item) {
+  @override
+  dynamic /*FutureOr<String>*/ matchAsync(item) {
     if (item is! Future) return 'was not a Future';
 
     return item.then((value) async {
@@ -70,6 +71,7 @@
     });
   }
 
+  @override
   Description describe(Description description) {
     if (_matcher == null) {
       description.add('completes successfully');
@@ -90,11 +92,13 @@
 class _DoesNotComplete extends Matcher {
   const _DoesNotComplete();
 
+  @override
   Description describe(Description description) {
     description.add('does not complete');
     return description;
   }
 
+  @override
   bool matches(item, Map matchState) {
     if (item is! Future) return false;
     item.then((value) {
@@ -105,6 +109,7 @@
     return true;
   }
 
+  @override
   Description describeMismatch(
       item, Description description, Map matchState, bool verbose) {
     if (item is! Future) return description.add('$item is not a Future');
diff --git a/pkgs/test_api/lib/src/frontend/prints_matcher.dart b/pkgs/test_api/lib/src/frontend/prints_matcher.dart
index c3618f1..48cf8a9 100644
--- a/pkgs/test_api/lib/src/frontend/prints_matcher.dart
+++ b/pkgs/test_api/lib/src/frontend/prints_matcher.dart
@@ -30,7 +30,8 @@
 
   // Avoid async/await so we synchronously fail if the function is
   // synchronous.
-  /*FutureOr<String>*/ matchAsync(item) {
+  @override
+  dynamic /*FutureOr<String>*/ matchAsync(item) {
     if (item is! Function()) return 'was not a unary Function';
 
     var buffer = StringBuffer();
@@ -44,6 +45,7 @@
         : _check(buffer.toString());
   }
 
+  @override
   Description describe(Description description) =>
       description.add('prints ').addDescriptionOf(_matcher);
 
diff --git a/pkgs/test_api/lib/src/frontend/stream_matcher.dart b/pkgs/test_api/lib/src/frontend/stream_matcher.dart
index f09d35b..7ba7f55 100644
--- a/pkgs/test_api/lib/src/frontend/stream_matcher.dart
+++ b/pkgs/test_api/lib/src/frontend/stream_matcher.dart
@@ -89,7 +89,7 @@
   /// should be grammatically valid when used after the word "should". For
   /// example, it might be "emit the right events".
   factory StreamMatcher(
-          Future<String> matchQueue(StreamQueue queue), String description) =
+          Future<String> Function(StreamQueue) matchQueue, String description) =
       _StreamMatcher;
 
   /// Tries to match events emitted by [queue].
@@ -116,6 +116,7 @@
 /// This is separate from the original type to hide the private [AsyncMatcher]
 /// interface.
 class _StreamMatcher extends AsyncMatcher implements StreamMatcher {
+  @override
   final String description;
 
   /// The callback used to implement [matchQueue].
@@ -123,9 +124,11 @@
 
   _StreamMatcher(this._matchQueue, this.description);
 
+  @override
   Future<String> matchQueue(StreamQueue queue) => _matchQueue(queue);
 
-  /*FutureOr<String>*/ matchAsync(item) {
+  @override
+  dynamic /*FutureOr<String>*/ matchAsync(item) {
     StreamQueue queue;
     if (item is StreamQueue) {
       queue = item;
@@ -185,6 +188,7 @@
     });
   }
 
+  @override
   Description describe(Description description) =>
       description.add('should ').add(this.description);
 }
diff --git a/pkgs/test_api/lib/src/frontend/stream_matchers.dart b/pkgs/test_api/lib/src/frontend/stream_matchers.dart
index d8fcb17..53f7c8c 100644
--- a/pkgs/test_api/lib/src/frontend/stream_matchers.dart
+++ b/pkgs/test_api/lib/src/frontend/stream_matchers.dart
@@ -199,7 +199,7 @@
   return StreamMatcher((queue) async {
     var failures = <String>[];
 
-    tryHere() => queue.withTransaction((copy) async {
+    Future<bool> tryHere() => queue.withTransaction((copy) async {
           var result = await streamMatcher.matchQueue(copy);
           if (result == null) return true;
           failures.add(result);
diff --git a/pkgs/test_api/lib/src/frontend/throws_matcher.dart b/pkgs/test_api/lib/src/frontend/throws_matcher.dart
index 8f389fc..cdf9c6e 100644
--- a/pkgs/test_api/lib/src/frontend/throws_matcher.dart
+++ b/pkgs/test_api/lib/src/frontend/throws_matcher.dart
@@ -42,11 +42,12 @@
 class Throws extends AsyncMatcher {
   final Matcher _matcher;
 
-  const Throws([Matcher matcher]) : this._matcher = matcher;
+  const Throws([Matcher matcher]) : _matcher = matcher;
 
   // Avoid async/await so we synchronously fail if we match a synchronous
   // function.
-  /*FutureOr<String>*/ matchAsync(item) {
+  @override
+  dynamic /*FutureOr<String>*/ matchAsync(item) {
     if (item is! Function && item is! Future) {
       return 'was not a Function or Future';
     }
@@ -71,6 +72,7 @@
     }
   }
 
+  @override
   Description describe(Description description) {
     if (_matcher == null) {
       return description.add('throws');
diff --git a/pkgs/test_api/lib/src/frontend/timeout.dart b/pkgs/test_api/lib/src/frontend/timeout.dart
index fde0aa9..6cad246 100644
--- a/pkgs/test_api/lib/src/frontend/timeout.dart
+++ b/pkgs/test_api/lib/src/frontend/timeout.dart
@@ -141,16 +141,19 @@
   /// If this is [none], returns `null`.
   Duration apply(Duration base) {
     if (this == none) return null;
-    return duration == null ? base * scaleFactor : duration;
+    return duration ?? base * scaleFactor;
   }
 
+  @override
   int get hashCode => duration.hashCode ^ 5 * scaleFactor.hashCode;
 
+  @override
   bool operator ==(other) =>
       other is Timeout &&
       other.duration == duration &&
       other.scaleFactor == scaleFactor;
 
+  @override
   String toString() {
     if (duration != null) return duration.toString();
     if (scaleFactor != null) return '${scaleFactor}x';
diff --git a/pkgs/test_api/lib/src/remote_listener.dart b/pkgs/test_api/lib/src/remote_listener.dart
index 5fbbd64..2f0979d 100644
--- a/pkgs/test_api/lib/src/remote_listener.dart
+++ b/pkgs/test_api/lib/src/remote_listener.dart
@@ -44,8 +44,8 @@
   ///
   /// If [beforeLoad] is passed, it's called before the tests have been declared
   /// for this worker.
-  static StreamChannel start(Function getMain(),
-      {bool hidePrints = true, Future beforeLoad()}) {
+  static StreamChannel start(Function Function() getMain,
+      {bool hidePrints = true, Future Function() beforeLoad}) {
     // This has to be synchronous to work around sdk#25745. Otherwise, there'll
     // be an asynchronous pause before a syntax error notification is sent,
     // which will cause the send to fail entirely.
@@ -121,7 +121,8 @@
 
           if (beforeLoad != null) await beforeLoad();
 
-          await declarer.declare(main as Function());
+          // TODO - is this await necessary?
+          await (declarer.declare(main as Function()) as dynamic);
 
           var suite = Suite(
               declarer.build(), SuitePlatform.deserialize(message['platform']),
diff --git a/pkgs/test_api/lib/src/suite_channel_manager.dart b/pkgs/test_api/lib/src/suite_channel_manager.dart
index aebe837..1f70d5f 100644
--- a/pkgs/test_api/lib/src/suite_channel_manager.dart
+++ b/pkgs/test_api/lib/src/suite_channel_manager.dart
@@ -20,7 +20,7 @@
   final _outgoingConnections = <String, StreamChannelCompleter>{};
 
   /// The channel names that have already been used.
-  final _names = Set<String>();
+  final _names = <String>{};
 
   /// Returns the current manager, or `null` if this isn't called within a call
   /// to [asCurrent].
@@ -31,7 +31,8 @@
   ///
   /// This is zone-scoped, so [this] will be the current configuration in any
   /// asynchronous callbacks transitively created by [body].
-  T asCurrent<T>(T body()) => runZoned(body, zoneValues: {_currentKey: this});
+  T asCurrent<T>(T Function() body) =>
+      runZoned(body, zoneValues: {_currentKey: this});
 
   /// Creates a connection to the test runnner's channel with the given [name].
   StreamChannel connectOut(String name) {
diff --git a/pkgs/test_api/lib/src/util/iterable_set.dart b/pkgs/test_api/lib/src/util/iterable_set.dart
index 5166a72..bba6433 100644
--- a/pkgs/test_api/lib/src/util/iterable_set.dart
+++ b/pkgs/test_api/lib/src/util/iterable_set.dart
@@ -19,17 +19,22 @@
   /// The base iterable that set operations forward to.
   final Iterable<E> _base;
 
+  @override
   int get length => _base.length;
 
+  @override
   Iterator<E> get iterator => _base.iterator;
 
   /// Creates a [Set] view of [base].
   IterableSet(this._base);
 
+  @override
   bool contains(Object element) => _base.contains(element);
 
+  @override
   E lookup(Object needle) =>
       _base.firstWhere((element) => element == needle, orElse: () => null);
 
+  @override
   Set<E> toSet() => _base.toSet();
 }
diff --git a/pkgs/test_api/lib/src/util/remote_exception.dart b/pkgs/test_api/lib/src/util/remote_exception.dart
index a0582d5..bb6fc62 100644
--- a/pkgs/test_api/lib/src/util/remote_exception.dart
+++ b/pkgs/test_api/lib/src/util/remote_exception.dart
@@ -29,7 +29,7 @@
   ///
   /// Other than JSON- and isolate-safety, no guarantees are made about the
   /// serialized format.
-  static serialize(error, StackTrace stackTrace) {
+  static Map<String, dynamic> serialize(error, StackTrace stackTrace) {
     String message;
     if (error is String) {
       message = error;
@@ -77,6 +77,7 @@
 
   RemoteException._(this.message, this.type, this._toString);
 
+  @override
   String toString() => _toString;
 }
 
diff --git a/pkgs/test_api/lib/src/util/test.dart b/pkgs/test_api/lib/src/util/test.dart
index ae5e6a8..de36fbf 100644
--- a/pkgs/test_api/lib/src/util/test.dart
+++ b/pkgs/test_api/lib/src/util/test.dart
@@ -13,7 +13,7 @@
 /// callbacks registered outside of [body].
 ///
 /// This may only be called within a test.
-Future errorsDontStopTest(body()) {
+Future errorsDontStopTest(dynamic Function() body) {
   var completer = Completer();
 
   Invoker.current.addOutstandingCallback();
diff --git a/pkgs/test_api/lib/src/utils.dart b/pkgs/test_api/lib/src/utils.dart
index 9b559b6..7229543 100644
--- a/pkgs/test_api/lib/src/utils.dart
+++ b/pkgs/test_api/lib/src/utils.dart
@@ -43,8 +43,13 @@
 /// Directories that are specific to OS X.
 ///
 /// This is used to try to distinguish OS X and Linux in [currentOSGuess].
-final _macOSDirectories = Set<String>.from(
-    ['/Applications', '/Library', '/Network', '/System', '/Users']);
+final _macOSDirectories = {
+  '/Applications',
+  '/Library',
+  '/Network',
+  '/System',
+  '/Users',
+};
 
 /// Returns the best guess for the current operating system without using
 /// `dart:io`.
@@ -77,13 +82,16 @@
 
   Pair(this.first, this.last);
 
+  @override
   String toString() => '($first, $last)';
 
+  @override
   bool operator ==(other) {
     if (other is! Pair) return false;
     return other.first == first && other.last == last;
   }
 
+  @override
   int get hashCode => first.hashCode ^ last.hashCode;
 }
 
@@ -141,7 +149,7 @@
 ///
 /// The return value *may or may not* be unmodifiable.
 Map<K, V> mergeUnmodifiableMaps<K, V>(Map<K, V> map1, Map<K, V> map2,
-    {V value(V value1, V value2)}) {
+    {V Function(V, V) value}) {
   if (map1.isEmpty) return map2;
   if (map2.isEmpty) return map1;
   return mergeMaps(map1, map2, value: value);
@@ -237,7 +245,7 @@
 ///
 /// This is useful for making a block of code async without forcing the
 /// containing method to return a future.
-void invoke(fn()) {
+void invoke(void Function() fn) {
   fn();
 }
 
diff --git a/pkgs/test_api/lib/test_api.dart b/pkgs/test_api/lib/test_api.dart
index 1c8a8a5..e43f5cc 100644
--- a/pkgs/test_api/lib/test_api.dart
+++ b/pkgs/test_api/lib/test_api.dart
@@ -94,7 +94,7 @@
 /// avoid this flag if possible and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTest
-void test(description, body(),
+void test(description, dynamic Function() body,
     {String testOn,
     Timeout timeout,
     skip,
@@ -172,7 +172,7 @@
 /// avoid this flag if possible, and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTestGroup
-void group(description, body(),
+void group(description, dynamic Function() body,
     {String testOn,
     Timeout timeout,
     skip,
@@ -207,7 +207,7 @@
 ///
 /// Each callback at the top level or in a given group will be run in the order
 /// they were declared.
-void setUp(callback()) => _declarer.setUp(callback);
+void setUp(dynamic Function() callback) => _declarer.setUp(callback);
 
 /// Registers a function to be run after tests.
 ///
@@ -222,7 +222,7 @@
 /// reverse of the order they were declared.
 ///
 /// See also [addTearDown], which adds tear-downs to a running test.
-void tearDown(callback()) => _declarer.tearDown(callback);
+void tearDown(dynamic Function() callback) => _declarer.tearDown(callback);
 
 /// Registers a function to be run after the current test.
 ///
@@ -235,7 +235,7 @@
 ///
 /// If this is called from within a [setUpAll] or [tearDownAll] callback, it
 /// instead runs the function after *all* tests in the current test suite.
-void addTearDown(callback()) {
+void addTearDown(dynamic Function() callback) {
   if (Invoker.current == null) {
     throw StateError('addTearDown() may only be called within a test.');
   }
@@ -256,7 +256,7 @@
 /// dependencies between tests that should be isolated. In general, you should
 /// prefer [setUp], and only use [setUpAll] if the callback is prohibitively
 /// slow.
-void setUpAll(callback()) => _declarer.setUpAll(callback);
+void setUpAll(dynamic Function() callback) => _declarer.setUpAll(callback);
 
 /// Registers a function to be run once after all tests.
 ///
@@ -269,7 +269,8 @@
 /// dependencies between tests that should be isolated. In general, you should
 /// prefer [tearDown], and only use [tearDownAll] if the callback is
 /// prohibitively slow.
-void tearDownAll(callback()) => _declarer.tearDownAll(callback);
+void tearDownAll(dynamic Function() callback) =>
+    _declarer.tearDownAll(callback);
 
 /// Registers an exception that was caught for the current test.
 void registerException(error, [StackTrace stackTrace]) {
diff --git a/pkgs/test_api/mono_pkg.yaml b/pkgs/test_api/mono_pkg.yaml
index 62b9aba..2fd0e73 100644
--- a/pkgs/test_api/mono_pkg.yaml
+++ b/pkgs/test_api/mono_pkg.yaml
@@ -6,7 +6,7 @@
         dart: dev
       - group:
         - dartanalyzer: --fatal-warnings .
-        dart: 2.1.0
+        dart: 2.3.0
     - unit_test:
       - group:
         - test: --preset travis
diff --git a/pkgs/test_api/pubspec.yaml b/pkgs/test_api/pubspec.yaml
index 165bced..3abd444 100644
--- a/pkgs/test_api/pubspec.yaml
+++ b/pkgs/test_api/pubspec.yaml
@@ -5,7 +5,7 @@
 homepage: https://github.com/dart-lang/test/blob/master/pkgs/test_api
 
 environment:
-  sdk: ">=2.2.0 <3.0.0"
+  sdk: ">=2.3.0 <3.0.0"
 
 dependencies:
   async: ^2.0.0
diff --git a/pkgs/test_api/test/backend/invoker_test.dart b/pkgs/test_api/test/backend/invoker_test.dart
index f2fc43d..9eef1fd 100644
--- a/pkgs/test_api/test/backend/invoker_test.dart
+++ b/pkgs/test_api/test/backend/invoker_test.dart
@@ -615,7 +615,7 @@
   });
 }
 
-LocalTest _localTest(body(), {Metadata metadata}) {
-  if (metadata == null) metadata = Metadata();
+LocalTest _localTest(dynamic Function() body, {Metadata metadata}) {
+  metadata ??= Metadata();
   return LocalTest('test', metadata, body);
 }
diff --git a/pkgs/test_api/test/backend/metadata_test.dart b/pkgs/test_api/test/backend/metadata_test.dart
index 56debdc..cb96b41 100644
--- a/pkgs/test_api/test/backend/metadata_test.dart
+++ b/pkgs/test_api/test/backend/metadata_test.dart
@@ -196,25 +196,23 @@
   group('validatePlatformSelectors', () {
     test('succeeds if onPlatform uses valid platforms', () {
       Metadata.parse(onPlatform: {'vm || browser': Skip()})
-          .validatePlatformSelectors(Set.from(['vm']));
+          .validatePlatformSelectors({'vm'});
     });
 
     test('succeeds if testOn uses valid platforms', () {
-      Metadata.parse(testOn: 'vm || browser')
-          .validatePlatformSelectors(Set.from(['vm']));
+      Metadata.parse(testOn: 'vm || browser').validatePlatformSelectors({'vm'});
     });
 
     test('fails if onPlatform uses an invalid platform', () {
       expect(() {
         Metadata.parse(onPlatform: {'unknown': Skip()})
-            .validatePlatformSelectors(Set.from(['vm']));
+            .validatePlatformSelectors({'vm'});
       }, throwsFormatException);
     });
 
     test('fails if testOn uses an invalid platform', () {
       expect(() {
-        Metadata.parse(testOn: 'unknown')
-            .validatePlatformSelectors(Set.from(['vm']));
+        Metadata.parse(testOn: 'unknown').validatePlatformSelectors({'vm'});
       }, throwsFormatException);
     });
   });
diff --git a/pkgs/test_api/test/utils.dart b/pkgs/test_api/test/utils.dart
index 25b5041..f1105dc 100644
--- a/pkgs/test_api/test/utils.dart
+++ b/pkgs/test_api/test/utils.dart
@@ -99,7 +99,7 @@
         .having((e) => e.message, 'message', message);
 
 /// Returns a local [LiveTest] that runs [body].
-LiveTest createTest(body()) {
+LiveTest createTest(dynamic Function() body) {
   var test = LocalTest('test', Metadata(), body);
   var suite = Suite(Group.root([test]), suitePlatform);
   return test.load(suite);
@@ -108,7 +108,7 @@
 /// Runs [body] as a test.
 ///
 /// Once it completes, returns the [LiveTest] used to run it.
-Future<LiveTest> runTestBody(body()) async {
+Future<LiveTest> runTestBody(dynamic Function() body) async {
   var liveTest = createTest(body);
   await liveTest.run();
   return liveTest;
@@ -144,7 +144,8 @@
 /// is called at some later time.
 ///
 /// [stopBlocking] is passed the return value of [test].
-Future expectTestBlocks(test(), stopBlocking(value)) async {
+Future expectTestBlocks(
+    dynamic Function() test, dynamic Function(dynamic) stopBlocking) async {
   LiveTest liveTest;
   Future future;
   liveTest = createTest(() {
@@ -167,7 +168,7 @@
 ///
 /// This is typically used to run multiple tests where later tests make
 /// assertions about the results of previous ones.
-Future expectTestsPass(void body()) async {
+Future expectTestsPass(void Function() body) async {
   var engine = declareEngine(body);
   var success = await engine.run();
 
@@ -179,13 +180,13 @@
 }
 
 /// Runs [body] with a declarer and returns the declared entries.
-List<GroupEntry> declare(void body()) {
+List<GroupEntry> declare(void Function() body) {
   var declarer = Declarer()..declare(body);
   return declarer.build().entries;
 }
 
 /// Runs [body] with a declarer and returns an engine that runs those tests.
-Engine declareEngine(void body(), {bool runSkipped = false}) {
+Engine declareEngine(void Function() body, {bool runSkipped = false}) {
   var declarer = Declarer()..declare(body);
   return Engine.withSuites([
     RunnerSuite(
diff --git a/pkgs/test_core/lib/src/bootstrap/vm.dart b/pkgs/test_core/lib/src/bootstrap/vm.dart
index a14dc43..41b9269 100644
--- a/pkgs/test_core/lib/src/bootstrap/vm.dart
+++ b/pkgs/test_core/lib/src/bootstrap/vm.dart
@@ -9,7 +9,7 @@
 import 'package:test_core/src/runner/plugin/remote_platform_helpers.dart';
 
 /// Bootstraps a vm test to communicate with the test runner.
-void internalBootstrapVmTest(Function getMain(), SendPort sendPort) {
+void internalBootstrapVmTest(Function Function() getMain, SendPort sendPort) {
   var channel = serializeSuite(getMain);
   IsolateChannel.connectSend(sendPort).pipe(channel);
 }
diff --git a/pkgs/test_core/lib/src/executable.dart b/pkgs/test_core/lib/src/executable.dart
index 942b361..70bfac4 100644
--- a/pkgs/test_core/lib/src/executable.dart
+++ b/pkgs/test_core/lib/src/executable.dart
@@ -36,7 +36,7 @@
   }
 }();
 
-main(List<String> args) async {
+void main(List<String> args) async {
   await _execute(args);
   completeShutdown();
 }
diff --git a/pkgs/test_core/lib/src/runner.dart b/pkgs/test_core/lib/src/runner.dart
index d16ec5b..9a9f9f9 100644
--- a/pkgs/test_core/lib/src/runner.dart
+++ b/pkgs/test_core/lib/src/runner.dart
@@ -58,7 +58,7 @@
   ///
   /// This is used to avoid printing duplicate warnings when a suite is loaded
   /// on multiple platforms.
-  final _tagWarningSuites = Set<String>();
+  final _tagWarningSuites = <String>{};
 
   /// The current debug operation, if any.
   ///
@@ -320,10 +320,10 @@
   /// This returns a map from tag names to lists of entries that use those tags.
   Map<String, List<GroupEntry>> _collectUnknownTags(Suite suite) {
     var unknownTags = <String, List<GroupEntry>>{};
-    var currentTags = Set<String>();
+    var currentTags = <String>{};
 
-    collect(GroupEntry entry) {
-      var newTags = Set<String>();
+    void collect(GroupEntry entry) {
+      var newTags = <String>{};
       for (var unknownTag
           in entry.metadata.tags.difference(_config.knownTags)) {
         if (currentTags.contains(unknownTag)) continue;
diff --git a/pkgs/test_core/lib/src/runner/application_exception.dart b/pkgs/test_core/lib/src/runner/application_exception.dart
index 919d3ec..23155a2 100644
--- a/pkgs/test_core/lib/src/runner/application_exception.dart
+++ b/pkgs/test_core/lib/src/runner/application_exception.dart
@@ -8,5 +8,6 @@
 
   ApplicationException(this.message);
 
+  @override
   String toString() => message;
 }
diff --git a/pkgs/test_core/lib/src/runner/compiler_pool.dart b/pkgs/test_core/lib/src/runner/compiler_pool.dart
index 22ffc49..7da937a 100644
--- a/pkgs/test_core/lib/src/runner/compiler_pool.dart
+++ b/pkgs/test_core/lib/src/runner/compiler_pool.dart
@@ -30,7 +30,7 @@
   final Pool _pool;
 
   /// The currently-active dart2js processes.
-  final _processes = Set<Process>();
+  final _processes = <Process>{};
 
   /// Whether [close] has been called.
   bool get _closed => _closeMemo.hasRun;
@@ -67,10 +67,10 @@
           '--enable-asserts',
           wrapperPath,
           '--out=$jsPath',
-          await PackageResolver.current.processArgument
-        ]
-          ..addAll(_extraArgs)
-          ..addAll(suiteConfig.dart2jsArgs);
+          await PackageResolver.current.processArgument,
+          ..._extraArgs,
+          ...suiteConfig.dart2jsArgs
+        ];
 
         if (_config.color) args.add('--enable-diagnostic-colors');
 
diff --git a/pkgs/test_core/lib/src/runner/configuration.dart b/pkgs/test_core/lib/src/runner/configuration.dart
index e8a02b5..7af26e7 100644
--- a/pkgs/test_core/lib/src/runner/configuration.dart
+++ b/pkgs/test_core/lib/src/runner/configuration.dart
@@ -112,12 +112,12 @@
   final int totalShards;
 
   /// The list of packages to fold when producing [StackTrace]s.
-  Set<String> get foldTraceExcept => _foldTraceExcept ?? Set();
+  Set<String> get foldTraceExcept => _foldTraceExcept ?? {};
   final Set<String> _foldTraceExcept;
 
   /// If non-empty, all packages not in this list will be folded when producing
   /// [StackTrace]s.
-  Set<String> get foldTraceOnly => _foldTraceOnly ?? Set();
+  Set<String> get foldTraceOnly => _foldTraceOnly ?? {};
   final Set<String> _foldTraceOnly;
 
   /// The paths from which to load tests.
@@ -362,7 +362,7 @@
         _foldTraceExcept = _set(foldTraceExcept),
         _foldTraceOnly = _set(foldTraceOnly),
         _filename = filename,
-        chosenPresets = UnmodifiableSetView(chosenPresets?.toSet() ?? Set()),
+        chosenPresets = UnmodifiableSetView(chosenPresets?.toSet() ?? {}),
         presets = _map(presets),
         overrideRuntimes = _map(overrideRuntimes),
         defineRuntimes = _map(defineRuntimes),
@@ -420,7 +420,8 @@
   ///
   /// This is zone-scoped, so [this] will be the current configuration in any
   /// asynchronous callbacks transitively created by [body].
-  T asCurrent<T>(T body()) => runZoned(body, zoneValues: {_currentKey: this});
+  T asCurrent<T>(T Function() body) =>
+      runZoned(body, zoneValues: {_currentKey: this});
 
   /// Throws a [FormatException] if [this] refers to any undefined runtimes.
   void validateRuntimes(List<Runtime> allRuntimes) {
@@ -615,12 +616,12 @@
             merged.merge(newPresets.remove(preset) ?? Configuration.empty));
 
     if (merged == empty) return this;
-    var result = this.change(presets: newPresets).merge(merged);
+    var result = change(presets: newPresets).merge(merged);
 
     // Make sure the configuration knows about presets that were selected and
     // thus removed from [newPresets].
-    result._knownPresets = UnmodifiableSetView(
-        result.knownPresets.toSet()..addAll(this.presets.keys));
+    result._knownPresets =
+        UnmodifiableSetView(result.knownPresets.toSet()..addAll(presets.keys));
 
     return result;
   }
diff --git a/pkgs/test_core/lib/src/runner/configuration/args.dart b/pkgs/test_core/lib/src/runner/configuration/args.dart
index 9101b7d..f71ae2d 100644
--- a/pkgs/test_core/lib/src/runner/configuration/args.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/args.dart
@@ -264,7 +264,7 @@
 
   /// Runs [parse] on the value of the option [name], and wraps any
   /// [FormatException] it throws with additional information.
-  T _parseOption<T>(String name, T parse(String value)) {
+  T _parseOption<T>(String name, T Function(String) parse) {
     if (!_options.wasParsed(name)) return null;
 
     var value = _options[name];
@@ -275,7 +275,7 @@
 
   /// Runs [parse], and wraps any [FormatException] it throws with additional
   /// information.
-  T _wrapFormatException<T>(String name, T parse()) {
+  T _wrapFormatException<T>(String name, T Function() parse) {
     try {
       return parse();
     } on FormatException catch (error) {
diff --git a/pkgs/test_core/lib/src/runner/configuration/load.dart b/pkgs/test_core/lib/src/runner/configuration/load.dart
index 45815b6..cf47a75 100644
--- a/pkgs/test_core/lib/src/runner/configuration/load.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/load.dart
@@ -418,7 +418,7 @@
 
   /// Throws an exception with [message] if [test] returns `false` when passed
   /// [node]'s value.
-  void _validate(YamlNode node, String message, bool test(value)) {
+  void _validate(YamlNode node, String message, bool Function(dynamic) test) {
     if (test(node.value)) return;
     throw SourceSpanFormatException(message, node.span, _source);
   }
@@ -427,7 +427,8 @@
   ///
   /// If [typeTest] returns `false` for that value, instead throws an error
   /// complaining that the field is not a [typeName].
-  _getValue(String field, String typeName, bool typeTest(value)) {
+  dynamic _getValue(
+      String field, String typeName, bool Function(dynamic) typeTest) {
     var value = _document[field];
     if (value == null || typeTest(value)) return value;
     _error('$field must be ${a(typeName)}.', field);
@@ -437,7 +438,8 @@
   ///
   /// If [typeTest] returns `false` for that node's value, instead throws an
   /// error complaining that the field is not a [typeName].
-  YamlNode _getNode(String field, String typeName, bool typeTest(value)) {
+  YamlNode _getNode(
+      String field, String typeName, bool Function(dynamic) typeTest) {
     var node = _document.nodes[field];
     if (node == null) return null;
     _validate(node, '$field must be ${a(typeName)}.', typeTest);
@@ -464,7 +466,7 @@
   /// contains.
   ///
   /// Returns a list of values returned by [forElement].
-  List<T> _getList<T>(String field, T forElement(YamlNode elementNode)) {
+  List<T> _getList<T>(String field, T Function(YamlNode) forElement) {
     var node = _getNode(field, 'list', (value) => value is List) as YamlList;
     if (node == null) return [];
     return node.nodes.map(forElement).toList();
@@ -475,7 +477,7 @@
   /// Returns a map with the keys and values returned by [key] and [value]. Each
   /// of these defaults to asserting that the value is a string.
   Map<K, V> _getMap<K, V>(String field,
-      {K key(YamlNode keyNode), V value(YamlNode valueNode)}) {
+      {K Function(YamlNode) key, V Function(YamlNode) value}) {
     var node = _getNode(field, 'map', (value) => value is Map) as YamlMap;
     if (node == null) return {};
 
@@ -523,7 +525,7 @@
   ///
   /// If [parse] throws a [FormatException], it's wrapped to include [node]'s
   /// span.
-  T _parseNode<T>(YamlNode node, String name, T parse(String value)) {
+  T _parseNode<T>(YamlNode node, String name, T Function(String) parse) {
     _validate(node, '$name must be a string.', (value) => value is String);
 
     try {
@@ -539,7 +541,7 @@
   ///
   /// If [parse] throws a [FormatException], it's wrapped to include [field]'s
   /// span.
-  T _parseValue<T>(String field, T parse(String value)) {
+  T _parseValue<T>(String field, T Function(String) parse) {
     var node = _document.nodes[field];
     if (node == null) return null;
     return _parseNode(node, field, parse);
@@ -569,7 +571,7 @@
   /// [SuiteConfiguration]s. The [create] function is used to construct
   /// [Configuration]s from the resolved maps.
   Configuration _extractPresets<T>(Map<T, Configuration> map,
-      Configuration create(Map<T, SuiteConfiguration> map)) {
+      Configuration Function(Map<T, SuiteConfiguration>) create) {
     if (map.isEmpty) return Configuration.empty;
 
     var base = <T, SuiteConfiguration>{};
diff --git a/pkgs/test_core/lib/src/runner/console.dart b/pkgs/test_core/lib/src/runner/console.dart
index 5e67e8f..ca4e14b 100644
--- a/pkgs/test_core/lib/src/runner/console.dart
+++ b/pkgs/test_core/lib/src/runner/console.dart
@@ -49,7 +49,8 @@
   /// The [description] should be a one-line description of the command to print
   /// in the help output. The [body] callback will be called when the user types
   /// the command, and may return a [Future].
-  void registerCommand(String name, String description, body()) {
+  void registerCommand(
+      String name, String description, dynamic Function() body) {
     if (_commands.containsKey(name)) {
       throw ArgumentError('The console already has a command named "$name".');
     }
diff --git a/pkgs/test_core/lib/src/runner/coverage.dart b/pkgs/test_core/lib/src/runner/coverage.dart
index 7dc2184..200019b 100644
--- a/pkgs/test_core/lib/src/runner/coverage.dart
+++ b/pkgs/test_core/lib/src/runner/coverage.dart
@@ -9,25 +9,24 @@
 import 'package:path/path.dart' as p;
 
 import 'live_suite_controller.dart';
-import 'runner_suite.dart';
 
 /// Collects coverage and outputs to the [coverage] path.
 Future<void> gatherCoverage(
     String coverage, LiveSuiteController controller) async {
-  final RunnerSuite suite = controller.liveSuite.suite;
+  final suite = controller.liveSuite.suite;
 
   if (!suite.platform.runtime.isDartVM) return;
 
-  final String isolateId = Uri.parse(suite.environment.observatoryUrl.fragment)
+  final isolateId = Uri.parse(suite.environment.observatoryUrl.fragment)
       .queryParameters['isolateId'];
 
   final cov = await collect(
-      suite.environment.observatoryUrl, false, false, false, Set(),
+      suite.environment.observatoryUrl, false, false, false, {},
       isolateIds: {isolateId});
 
   final outfile = File(p.join('$coverage', '${suite.path}.vm.json'))
     ..createSync(recursive: true);
-  final IOSink out = outfile.openWrite();
+  final out = outfile.openWrite();
   out.write(json.encode(cov));
   await out.flush();
   await out.close();
diff --git a/pkgs/test_core/lib/src/runner/engine.dart b/pkgs/test_core/lib/src/runner/engine.dart
index 5fe52e5..cf7dbd6 100644
--- a/pkgs/test_core/lib/src/runner/engine.dart
+++ b/pkgs/test_core/lib/src/runner/engine.dart
@@ -108,7 +108,7 @@
   final _group = FutureGroup();
 
   /// All of the engine's stream subscriptions.
-  final _subscriptions = Set<StreamSubscription>();
+  final _subscriptions = <StreamSubscription>{};
 
   /// A sink used to pass [RunnerSuite]s in to the engine to run.
   ///
@@ -125,7 +125,7 @@
   /// Note that if a [LoadSuite] is added, this will only contain that suite,
   /// not the suite it loads.
   Set<RunnerSuite> get addedSuites => UnmodifiableSetView(_addedSuites);
-  final _addedSuites = Set<RunnerSuite>();
+  final _addedSuites = <RunnerSuite>{};
 
   /// A broadcast stream that emits each [RunnerSuite] as it's added to the
   /// engine via [suiteSink].
@@ -146,7 +146,7 @@
   /// [LoadSuite]s, both the [LoadSuite] and the suite it loads will eventually
   /// be in this set.
   Set<LiveSuite> get liveSuites => UnmodifiableSetView(_liveSuites);
-  final _liveSuites = Set<LiveSuite>();
+  final _liveSuites = <LiveSuite>{};
 
   /// A broadcast stream that emits each [LiveSuite] as it's loaded.
   ///
@@ -196,13 +196,13 @@
   ///
   /// This is always a subset of [active]. Once a test in here has finished
   /// running, it's run again.
-  final _restarted = Set<LiveTest>();
+  final _restarted = <LiveTest>{};
 
   /// The tests from [LoadSuite]s that are still running, in the order they
   /// began running.
   ///
   /// This is separate from [active] because load tests aren't always surfaced.
-  final _activeLoadTests = List<LiveTest>();
+  final _activeLoadTests = <LiveTest>{};
 
   /// Whether this engine is idle—that is, not currently executing a test.
   bool get isIdle => _group.isIdle;
@@ -225,7 +225,7 @@
     _group.future.then((_) {
       _onTestStartedGroup.close();
       _onSuiteStartedController.close();
-      if (_closedBeforeDone == null) _closedBeforeDone = false;
+      _closedBeforeDone ??= false;
     }).catchError((_) {
       // Don't top-level errors. They'll be thrown via [success] anyway.
     });
diff --git a/pkgs/test_core/lib/src/runner/environment.dart b/pkgs/test_core/lib/src/runner/environment.dart
index 31a2678..2ddfdb3 100644
--- a/pkgs/test_core/lib/src/runner/environment.dart
+++ b/pkgs/test_core/lib/src/runner/environment.dart
@@ -36,15 +36,20 @@
 
 /// The default environment for platform plugins.
 class PluginEnvironment implements Environment {
+  @override
   final supportsDebugging = false;
+  @override
   Stream get onRestart => StreamController.broadcast().stream;
 
   const PluginEnvironment();
 
+  @override
   Uri get observatoryUrl => null;
 
+  @override
   Uri get remoteDebuggerUrl => null;
 
+  @override
   CancelableOperation displayPause() => throw UnsupportedError(
       'PluginEnvironment.displayPause is not supported.');
 }
diff --git a/pkgs/test_core/lib/src/runner/hybrid_listener.dart b/pkgs/test_core/lib/src/runner/hybrid_listener.dart
index 06e5e6b..36e8242 100644
--- a/pkgs/test_core/lib/src/runner/hybrid_listener.dart
+++ b/pkgs/test_core/lib/src/runner/hybrid_listener.dart
@@ -32,7 +32,7 @@
 ///
 /// The [data] argument contains two values: a [SendPort] that communicates with
 /// the main isolate, and a message to pass to `hybridMain()`.
-void listen(Function getMain(), List data) {
+void listen(Function Function() getMain, List data) {
   var channel = IsolateChannel.connectSend(data.first as SendPort);
   var message = data.last;
 
diff --git a/pkgs/test_core/lib/src/runner/live_suite.dart b/pkgs/test_core/lib/src/runner/live_suite.dart
index 9c84492..e580845 100644
--- a/pkgs/test_core/lib/src/runner/live_suite.dart
+++ b/pkgs/test_core/lib/src/runner/live_suite.dart
@@ -59,11 +59,12 @@
   ///
   /// This is guaranteed to contain the same tests as the union of [passed],
   /// [skipped], [failed], and [active].
-  Set<LiveTest> get liveTests {
-    var sets = [passed, skipped, failed];
-    if (active != null) sets.add(Set.from([active]));
-    return UnionSet.from(sets);
-  }
+  Set<LiveTest> get liveTests => UnionSet.from([
+        passed,
+        skipped,
+        failed,
+        if (active != null) {active}
+      ]);
 
   /// A stream that emits each [LiveTest] in this suite as it's about to start
   /// running.
diff --git a/pkgs/test_core/lib/src/runner/live_suite_controller.dart b/pkgs/test_core/lib/src/runner/live_suite_controller.dart
index e33bfde..e2ec1dc 100644
--- a/pkgs/test_core/lib/src/runner/live_suite_controller.dart
+++ b/pkgs/test_core/lib/src/runner/live_suite_controller.dart
@@ -18,25 +18,35 @@
 class _LiveSuite extends LiveSuite {
   final LiveSuiteController _controller;
 
+  @override
   RunnerSuite get suite => _controller._suite;
 
+  @override
   bool get isComplete => _controller._isComplete;
 
+  @override
   Future get onComplete => _controller._onCompleteGroup.future;
 
+  @override
   bool get isClosed => _controller._onCloseCompleter.isCompleted;
 
+  @override
   Future get onClose => _controller._onCloseCompleter.future;
 
+  @override
   Stream<LiveTest> get onTestStarted =>
       _controller._onTestStartedController.stream;
 
+  @override
   Set<LiveTest> get passed => UnmodifiableSetView(_controller._passed);
 
+  @override
   Set<LiveTest> get skipped => UnmodifiableSetView(_controller._skipped);
 
+  @override
   Set<LiveTest> get failed => UnmodifiableSetView(_controller._failed);
 
+  @override
   LiveTest get active => _controller._active;
 
   _LiveSuite(this._controller);
@@ -76,13 +86,13 @@
       StreamController<LiveTest>.broadcast(sync: true);
 
   /// The set that backs [LiveTest.passed].
-  final _passed = Set<LiveTest>();
+  final _passed = <LiveTest>{};
 
   /// The set that backs [LiveTest.skipped].
-  final _skipped = Set<LiveTest>();
+  final _skipped = <LiveTest>{};
 
   /// The set that backs [LiveTest.failed].
-  final _failed = Set<LiveTest>();
+  final _failed = <LiveTest>{};
 
   /// The test exposed through [LiveTest.active].
   LiveTest _active;
diff --git a/pkgs/test_core/lib/src/runner/load_exception.dart b/pkgs/test_core/lib/src/runner/load_exception.dart
index 6969ce3..dcc5f17 100644
--- a/pkgs/test_core/lib/src/runner/load_exception.dart
+++ b/pkgs/test_core/lib/src/runner/load_exception.dart
@@ -12,6 +12,7 @@
 
   LoadException(this.path, this.innerError);
 
+  @override
   String toString({bool color = false}) {
     var buffer = StringBuffer();
     if (color) buffer.write('\u001b[31m'); // red
diff --git a/pkgs/test_core/lib/src/runner/load_suite.dart b/pkgs/test_core/lib/src/runner/load_suite.dart
index 3613bfb..24ce420 100644
--- a/pkgs/test_core/lib/src/runner/load_suite.dart
+++ b/pkgs/test_core/lib/src/runner/load_suite.dart
@@ -51,9 +51,13 @@
 /// suite itself is returned by [suite] once it's avaialble, but any errors or
 /// prints will be emitted through the running [LiveTest].
 class LoadSuite extends Suite implements RunnerSuite {
+  @override
   final environment = const PluginEnvironment();
+  @override
   final SuiteConfiguration config;
+  @override
   final isDebugging = false;
+  @override
   final onDebugging = StreamController<bool>().stream;
 
   @override
@@ -87,7 +91,7 @@
   /// If the the load test is closed before [body] is complete, it will close
   /// the suite returned by [body] once it completes.
   factory LoadSuite(String name, SuiteConfiguration config,
-      SuitePlatform platform, FutureOr<RunnerSuite> body(),
+      SuitePlatform platform, FutureOr<RunnerSuite> Function() body,
       {String path}) {
     var completer = Completer<Pair<RunnerSuite, Zone>>.sync();
     return LoadSuite._(name, config, platform, () {
@@ -126,7 +130,7 @@
   factory LoadSuite.forLoadException(
       LoadException exception, SuiteConfiguration config,
       {SuitePlatform platform, StackTrace stackTrace}) {
-    if (stackTrace == null) stackTrace = Trace.current();
+    stackTrace ??= Trace.current();
 
     return LoadSuite(
         'loading ${exception.path}',
@@ -143,8 +147,8 @@
         path: suite.path);
   }
 
-  LoadSuite._(String name, this.config, SuitePlatform platform, void body(),
-      this._suiteAndZone, {String path})
+  LoadSuite._(String name, this.config, SuitePlatform platform,
+      void Function() body, this._suiteAndZone, {String path})
       : super(
             Group.root(
                 [LocalTest(name, Metadata(timeout: Timeout(_timeout)), body)]),
@@ -168,7 +172,7 @@
   /// If [suite] completes to `null`, [change] won't be run. [change] is run
   /// within the load test's zone, so any errors or prints it emits will be
   /// associated with that test.
-  LoadSuite changeSuite(RunnerSuite change(RunnerSuite suite)) {
+  LoadSuite changeSuite(RunnerSuite Function(RunnerSuite) change) {
     return LoadSuite._changeSuite(this, _suiteAndZone.then((pair) {
       if (pair == null) return null;
 
@@ -197,14 +201,17 @@
     throw 'unreachable';
   }
 
-  LoadSuite filter(bool callback(Test test)) {
+  @override
+  LoadSuite filter(bool Function(Test) callback) {
     var filtered = this.group.filter(callback);
-    if (filtered == null) filtered = Group.root([], metadata: metadata);
+    filtered ??= Group.root([], metadata: metadata);
     return LoadSuite._filtered(this, filtered);
   }
 
+  @override
   StreamChannel channel(String name) =>
       throw UnsupportedError('LoadSuite.channel() is not supported.');
 
+  @override
   Future close() async {}
 }
diff --git a/pkgs/test_core/lib/src/runner/loader.dart b/pkgs/test_core/lib/src/runner/loader.dart
index 6d860f0..d21e26c 100644
--- a/pkgs/test_core/lib/src/runner/loader.dart
+++ b/pkgs/test_core/lib/src/runner/loader.dart
@@ -35,7 +35,7 @@
   final _config = Configuration.current;
 
   /// All suites that have been created by the loader.
-  final _suites = Set<RunnerSuite>();
+  final _suites = <RunnerSuite>{};
 
   /// Memoizers for platform plugins, indexed by the runtimes they support.
   final _platformPlugins = <Runtime, AsyncMemoizer<PlatformPlugin>>{};
diff --git a/pkgs/test_core/lib/src/runner/parse_metadata.dart b/pkgs/test_core/lib/src/runner/parse_metadata.dart
index 40366a2..1de3d33 100644
--- a/pkgs/test_core/lib/src/runner/parse_metadata.dart
+++ b/pkgs/test_core/lib/src/runner/parse_metadata.dart
@@ -42,7 +42,7 @@
   Set<String> _prefixes;
 
   /// The actual contents of the file.
-  String _contents;
+  final String _contents;
 
   _Parser(this._path, this._contents, this._platformVariables) {
     // ignore: deprecated_member_use
@@ -162,7 +162,7 @@
   /// constructor for the annotation, if any.
   ///
   /// Returns either `true` or a reason string.
-  _parseSkip(Annotation annotation, String constructorName) {
+  dynamic _parseSkip(Annotation annotation, String constructorName) {
     var args = annotation.arguments.arguments;
     return args.isEmpty ? true : _parseString(args.first).stringValue;
   }
@@ -170,7 +170,7 @@
   /// Parses a `Skip` constructor.
   ///
   /// Returns either `true` or a reason string.
-  _parseSkipConstructor(Expression constructor) {
+  dynamic _parseSkipConstructor(Expression constructor) {
     _findConstructorName(constructor, 'Skip');
     var arguments = _parseArguments(constructor);
     return arguments.isEmpty ? true : _parseString(arguments.first).stringValue;
@@ -283,9 +283,10 @@
 
   Map<String, Expression> _parseNamedArguments(
           NodeList<Expression> arguments) =>
-      Map.fromIterable(arguments.whereType<NamedExpression>(),
-          key: (a) => (a as NamedExpression).name.label.name,
-          value: (a) => (a as NamedExpression).expression);
+      {
+        for (var a in arguments.whereType<NamedExpression>())
+          a.name.label.name: a.expression
+      };
 
   /// Asserts that [existing] is null.
   ///
@@ -435,7 +436,7 @@
   /// By default, returns [Expression] keys and values. These can be overridden
   /// with the [key] and [value] parameters.
   Map<K, V> _parseMap<K, V>(Expression expression,
-      {K key(Expression expression), V value(Expression expression)}) {
+      {K Function(Expression) key, V Function(Expression) value}) {
     key ??= (expression) => expression as K;
     value ??= (expression) => expression as V;
 
@@ -505,7 +506,7 @@
 
   /// Runs [fn] and contextualizes any [SourceSpanFormatException]s that occur
   /// in it relative to [literal].
-  T _contextualize<T>(StringLiteral literal, T fn()) {
+  T _contextualize<T>(StringLiteral literal, T Function() fn) {
     try {
       return fn();
     } on SourceSpanFormatException catch (error) {
diff --git a/pkgs/test_core/lib/src/runner/plugin/environment.dart b/pkgs/test_core/lib/src/runner/plugin/environment.dart
index b6c1edd..40e88b2 100644
--- a/pkgs/test_core/lib/src/runner/plugin/environment.dart
+++ b/pkgs/test_core/lib/src/runner/plugin/environment.dart
@@ -10,15 +10,20 @@
 
 /// The default environment for platform plugins.
 class PluginEnvironment implements Environment {
+  @override
   final supportsDebugging = false;
+  @override
   Stream get onRestart => StreamController.broadcast().stream;
 
   const PluginEnvironment();
 
+  @override
   Uri get observatoryUrl => null;
 
+  @override
   Uri get remoteDebuggerUrl => null;
 
+  @override
   CancelableOperation displayPause() => throw UnsupportedError(
       'PluginEnvironment.displayPause is not supported.');
 }
diff --git a/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart b/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
index 0b64171..a353d57 100644
--- a/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
+++ b/pkgs/test_core/lib/src/runner/plugin/platform_helpers.dart
@@ -60,7 +60,7 @@
   var completer = Completer<Group>();
 
   var loadSuiteZone = Zone.current;
-  handleError(error, StackTrace stackTrace) {
+  void handleError(error, StackTrace stackTrace) {
     disconnector.disconnect();
 
     if (completer.isCompleted) {
diff --git a/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart b/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
index 310d0f5..17c6d4c 100644
--- a/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
+++ b/pkgs/test_core/lib/src/runner/plugin/remote_platform_helpers.dart
@@ -30,8 +30,8 @@
 ///
 /// If [beforeLoad] is passed, it's called before the tests have been declared
 /// for this worker.
-StreamChannel serializeSuite(Function getMain(),
-        {bool hidePrints = true, Future beforeLoad()}) =>
+StreamChannel serializeSuite(Function Function() getMain,
+        {bool hidePrints = true, Future Function() beforeLoad}) =>
     RemoteListener.start(getMain,
         hidePrints: hidePrints, beforeLoad: beforeLoad);
 
diff --git a/pkgs/test_core/lib/src/runner/reporter/compact.dart b/pkgs/test_core/lib/src/runner/reporter/compact.dart
index aa356ed..4c3e69a 100644
--- a/pkgs/test_core/lib/src/runner/reporter/compact.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/compact.dart
@@ -99,7 +99,7 @@
   var _paused = false;
 
   /// The set of all subscriptions to various streams.
-  final _subscriptions = Set<StreamSubscription>();
+  final _subscriptions = <StreamSubscription>{};
 
   /// Watches the tests run by [engine] and prints their results to the
   /// terminal.
@@ -114,6 +114,7 @@
     _subscriptions.add(_engine.success.asStream().listen(_onDone));
   }
 
+  @override
   void pause() {
     if (_paused) return;
     _paused = true;
@@ -132,6 +133,7 @@
     }
   }
 
+  @override
   void resume() {
     if (!_paused) return;
     _paused = false;
@@ -143,6 +145,7 @@
     }
   }
 
+  @override
   void cancel() {
     for (var subscription in _subscriptions) {
       subscription.cancel();
@@ -309,7 +312,7 @@
     _lastProgressTruncated = truncate;
 
     if (suffix != null) message += suffix;
-    if (color == null) color = '';
+    color ??= '';
     var duration = _stopwatch.elapsed;
     var buffer = StringBuffer();
 
diff --git a/pkgs/test_core/lib/src/runner/reporter/expanded.dart b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
index 5a50c9d..2785ae9 100644
--- a/pkgs/test_core/lib/src/runner/reporter/expanded.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/expanded.dart
@@ -82,7 +82,7 @@
   var _paused = false;
 
   /// The set of all subscriptions to various streams.
-  final _subscriptions = Set<StreamSubscription>();
+  final _subscriptions = <StreamSubscription>{};
 
   final StringSink _sink;
 
@@ -119,6 +119,7 @@
     _subscriptions.add(_engine.success.asStream().listen(_onDone));
   }
 
+  @override
   void pause() {
     if (_paused) return;
     _paused = true;
@@ -130,6 +131,7 @@
     }
   }
 
+  @override
   void resume() {
     if (!_paused) return;
     _stopwatch.start();
@@ -139,6 +141,7 @@
     }
   }
 
+  @override
   void cancel() {
     for (var subscription in _subscriptions) {
       subscription.cancel();
@@ -258,7 +261,7 @@
     _lastProgressSuffix = suffix;
 
     if (suffix != null) message += suffix;
-    if (color == null) color = '';
+    color ??= '';
     var duration = _stopwatch.elapsed;
     var buffer = StringBuffer();
 
diff --git a/pkgs/test_core/lib/src/runner/reporter/json.dart b/pkgs/test_core/lib/src/runner/reporter/json.dart
index 6abbacc..5edb4a0 100644
--- a/pkgs/test_core/lib/src/runner/reporter/json.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/json.dart
@@ -48,16 +48,16 @@
   var _paused = false;
 
   /// The set of all subscriptions to various streams.
-  final _subscriptions = Set<StreamSubscription>();
+  final _subscriptions = <StreamSubscription>{};
 
   /// An expando that associates unique IDs with [LiveTest]s.
-  final _liveTestIDs = Map<LiveTest, int>();
+  final _liveTestIDs = <LiveTest, int>{};
 
   /// An expando that associates unique IDs with [Suite]s.
-  final _suiteIDs = Map<Suite, int>();
+  final _suiteIDs = <Suite, int>{};
 
   /// An expando that associates unique IDs with [Group]s.
-  final _groupIDs = Map<Group, int>();
+  final _groupIDs = <Group, int>{};
 
   /// The next ID to associate with a [LiveTest].
   var _nextID = 0;
@@ -81,6 +81,7 @@
         {'protocolVersion': '0.1.1', 'runnerVersion': testVersion, 'pid': pid});
   }
 
+  @override
   void pause() {
     if (_paused) return;
     _paused = true;
@@ -92,6 +93,7 @@
     }
   }
 
+  @override
   void resume() {
     if (!_paused) return;
     _paused = false;
@@ -103,6 +105,7 @@
     }
   }
 
+  @override
   void cancel() {
     for (var subscription in _subscriptions) {
       subscription.cancel();
diff --git a/pkgs/test_core/lib/src/runner/runner_suite.dart b/pkgs/test_core/lib/src/runner/runner_suite.dart
index 3c921ec..8470f62 100644
--- a/pkgs/test_core/lib/src/runner/runner_suite.dart
+++ b/pkgs/test_core/lib/src/runner/runner_suite.dart
@@ -68,7 +68,8 @@
       this._controller, Group group, String path, SuitePlatform platform)
       : super(group, platform, path: path);
 
-  RunnerSuite filter(bool callback(Test test)) {
+  @override
+  RunnerSuite filter(bool Function(Test) callback) {
     var filtered = group.filter(callback);
     filtered ??= Group.root([], metadata: metadata);
     return RunnerSuite._(_controller, filtered, path, platform);
@@ -103,7 +104,7 @@
   final _onDebuggingController = StreamController<bool>.broadcast();
 
   /// The channel names that have already been used.
-  final _channelNames = Set<String>();
+  final _channelNames = <String>{};
 
   RunnerSuiteController(this._environment, this._config, this._suiteChannel,
       Future<Group> groupFuture, SuitePlatform platform,
diff --git a/pkgs/test_core/lib/src/runner/runner_test.dart b/pkgs/test_core/lib/src/runner/runner_test.dart
index f19cad1..7f828b7 100644
--- a/pkgs/test_core/lib/src/runner/runner_test.dart
+++ b/pkgs/test_core/lib/src/runner/runner_test.dart
@@ -21,8 +21,11 @@
 
 /// A test running remotely, controlled by a stream channel.
 class RunnerTest extends Test {
+  @override
   final String name;
+  @override
   final Metadata metadata;
+  @override
   final Trace trace;
 
   /// The channel used to communicate with the test's [IframeListener].
@@ -32,6 +35,7 @@
 
   RunnerTest._(this.name, this.metadata, this.trace, this._channel);
 
+  @override
   LiveTest load(Suite suite, {Iterable<Group> groups}) {
     LiveTestController controller;
     VirtualChannel testChannel;
@@ -97,6 +101,7 @@
     return controller.liveTest;
   }
 
+  @override
   Test forPlatform(SuitePlatform platform) {
     if (!metadata.testOn.evaluate(platform)) return null;
     return RunnerTest._(name, metadata.forPlatform(platform), trace, _channel);
diff --git a/pkgs/test_core/lib/src/runner/runtime_selection.dart b/pkgs/test_core/lib/src/runner/runtime_selection.dart
index 0585a0f..8105dcd 100644
--- a/pkgs/test_core/lib/src/runner/runtime_selection.dart
+++ b/pkgs/test_core/lib/src/runner/runtime_selection.dart
@@ -16,7 +16,9 @@
 
   RuntimeSelection(this.name, [this.span]);
 
+  @override
   bool operator ==(other) => other is RuntimeSelection && other.name == name;
 
+  @override
   int get hashCode => name.hashCode;
 }
diff --git a/pkgs/test_core/lib/src/runner/suite.dart b/pkgs/test_core/lib/src/runner/suite.dart
index a685640..d88c992 100644
--- a/pkgs/test_core/lib/src/runner/suite.dart
+++ b/pkgs/test_core/lib/src/runner/suite.dart
@@ -196,7 +196,7 @@
       : _jsTrace = jsTrace,
         _runSkipped = runSkipped,
         dart2jsArgs = _list(dart2jsArgs) ?? const [],
-        patterns = UnmodifiableSetView(patterns?.toSet() ?? Set()),
+        patterns = UnmodifiableSetView(patterns?.toSet() ?? {}),
         _runtimes = _list(runtimes),
         includeTags = includeTags ?? BooleanSelector.all,
         excludeTags = excludeTags ?? BooleanSelector.none,
@@ -369,6 +369,6 @@
     });
 
     if (merged == empty) return this;
-    return this.change(tags: newTags).merge(merged);
+    return change(tags: newTags).merge(merged);
   }
 }
diff --git a/pkgs/test_core/lib/src/runner/vm/environment.dart b/pkgs/test_core/lib/src/runner/vm/environment.dart
index 6fedbec..6f919bf 100644
--- a/pkgs/test_core/lib/src/runner/vm/environment.dart
+++ b/pkgs/test_core/lib/src/runner/vm/environment.dart
@@ -10,7 +10,9 @@
 
 /// The environment in which VM tests are loaded.
 class VMEnvironment implements Environment {
+  @override
   final supportsDebugging = true;
+  @override
   final Uri observatoryUrl;
 
   /// The VM service isolate object used to control this isolate.
@@ -19,10 +21,13 @@
 
   VMEnvironment(this.observatoryUrl, this._isolate, this._client);
 
+  @override
   Uri get remoteDebuggerUrl => null;
 
+  @override
   Stream get onRestart => StreamController.broadcast().stream;
 
+  @override
   CancelableOperation displayPause() {
     var completer =
         CancelableCompleter(onCancel: () => _client.resume(_isolate.id));
diff --git a/pkgs/test_core/lib/src/runner/vm/platform.dart b/pkgs/test_core/lib/src/runner/vm/platform.dart
index a095b72..34853ea 100644
--- a/pkgs/test_core/lib/src/runner/vm/platform.dart
+++ b/pkgs/test_core/lib/src/runner/vm/platform.dart
@@ -33,9 +33,11 @@
 
   VMPlatform();
 
+  @override
   StreamChannel loadChannel(String path, SuitePlatform platform) =>
       throw UnimplementedError();
 
+  @override
   Future<RunnerSuite> load(String path, SuitePlatform platform,
       SuiteConfiguration suiteConfig, Object message) async {
     assert(platform.runtime == Runtime.vm);
diff --git a/pkgs/test_core/lib/src/util/io.dart b/pkgs/test_core/lib/src/util/io.dart
index d344953..98b2ad9 100644
--- a/pkgs/test_core/lib/src/util/io.dart
+++ b/pkgs/test_core/lib/src/util/io.dart
@@ -92,7 +92,7 @@
 ///
 /// Returns a future that completes to the value that the future returned from
 /// [fn] completes to.
-Future withTempDir(Future fn(String path)) {
+Future withTempDir(Future Function(String) fn) {
   return Future.sync(() {
     var tempDir = createTempDir();
     return Future.sync(() => fn(tempDir))
@@ -139,7 +139,7 @@
 /// If [print] is `true`, this prints the message using [print] to associate it
 /// with the current test. Otherwise, it prints it using [stderr].
 void warn(String message, {bool color, bool print = false}) {
-  if (color == null) color = canUseSpecialChars;
+  color ??= canUseSpecialChars;
   var header = color ? '\u001b[33mWarning:\u001b[0m' : 'Warning:';
   (print ? core.print : stderr.writeln)(wordWrap('$header $message\n'));
 }
@@ -153,7 +153,7 @@
 ///
 /// This is necessary for ensuring that our port binding isn't flaky for
 /// applications that don't print out the bound port.
-Future<T> getUnusedPort<T>(FutureOr<T> tryPort(int port)) async {
+Future<T> getUnusedPort<T>(FutureOr<T> Function(int port) tryPort) async {
   T value;
   await Future.doWhile(() async {
     value = await tryPort(await getUnsafeUnusedPort());
diff --git a/pkgs/test_core/lib/src/util/stack_trace_mapper.dart b/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
index d99608c..2d2b0bf 100644
--- a/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
+++ b/pkgs/test_core/lib/src/util/stack_trace_mapper.dart
@@ -33,6 +33,7 @@
         _sdkRoot = sdkRoot;
 
   /// Converts [trace] into a Dart stack trace.
+  @override
   StackTrace mapStackTrace(StackTrace trace) {
     _mapping ??= parseExtended(_mapContents, mapUrl: _mapUrl);
     return mapper.mapStackTrace(_mapping, trace,
@@ -40,6 +41,7 @@
   }
 
   /// Returns a Map representation which is suitable for JSON serialization.
+  @override
   Map<String, dynamic> serialize() {
     return {
       'mapContents': _mapContents,
@@ -55,7 +57,7 @@
   /// representation.
   static StackTraceMapper deserialize(Map serialized) {
     if (serialized == null) return null;
-    String packageRoot = serialized['packageRoot'] as String ?? '';
+    var packageRoot = serialized['packageRoot'] as String ?? '';
     return JSStackTraceMapper(serialized['mapContents'] as String,
         sdkRoot: Uri.parse(serialized['sdkRoot'] as String),
         packageResolver: packageRoot.isNotEmpty
diff --git a/pkgs/test_core/lib/src/util/string_literal_iterator.dart b/pkgs/test_core/lib/src/util/string_literal_iterator.dart
index 6b340c2..24caa08 100644
--- a/pkgs/test_core/lib/src/util/string_literal_iterator.dart
+++ b/pkgs/test_core/lib/src/util/string_literal_iterator.dart
@@ -37,6 +37,7 @@
 /// In addition to exposing the values of the runes themselves, this also
 /// exposes the offset of the current rune in the Dart source file.
 class StringLiteralIterator extends Iterator<int> {
+  @override
   int get current => _current;
   int _current;
 
@@ -96,6 +97,7 @@
     _offset = _strings.first.contentsOffset - 1;
   }
 
+  @override
   bool moveNext() {
     // If we're at beginning of a [SimpleStringLiteral], move forward until
     // there's actually text to consume.
diff --git a/pkgs/test_core/lib/test_core.dart b/pkgs/test_core/lib/test_core.dart
index f72fb02..b7cdae9 100644
--- a/pkgs/test_core/lib/test_core.dart
+++ b/pkgs/test_core/lib/test_core.dart
@@ -129,7 +129,7 @@
 /// avoid this flag if possible and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTest
-void test(description, body(),
+void test(description, dynamic Function() body,
     {String testOn,
     Timeout timeout,
     skip,
@@ -207,7 +207,7 @@
 /// avoid this flag if possible, and instead use the test runner flag `-n` to
 /// filter tests by name.
 @isTestGroup
-void group(description, body(),
+void group(description, dynamic Function() body,
     {String testOn,
     Timeout timeout,
     skip,
@@ -242,7 +242,7 @@
 ///
 /// Each callback at the top level or in a given group will be run in the order
 /// they were declared.
-void setUp(callback()) => _declarer.setUp(callback);
+void setUp(dynamic Function() callback) => _declarer.setUp(callback);
 
 /// Registers a function to be run after tests.
 ///
@@ -257,7 +257,7 @@
 /// reverse of the order they were declared.
 ///
 /// See also [addTearDown], which adds tear-downs to a running test.
-void tearDown(callback()) => _declarer.tearDown(callback);
+void tearDown(dynamic Function() callback) => _declarer.tearDown(callback);
 
 /// Registers a function to be run once before all tests.
 ///
@@ -272,7 +272,7 @@
 /// dependencies between tests that should be isolated. In general, you should
 /// prefer [setUp], and only use [setUpAll] if the callback is prohibitively
 /// slow.
-void setUpAll(callback()) => _declarer.setUpAll(callback);
+void setUpAll(dynamic Function() callback) => _declarer.setUpAll(callback);
 
 /// Registers a function to be run once after all tests.
 ///
@@ -285,4 +285,5 @@
 /// dependencies between tests that should be isolated. In general, you should
 /// prefer [tearDown], and only use [tearDownAll] if the callback is
 /// prohibitively slow.
-void tearDownAll(callback()) => _declarer.tearDownAll(callback);
+void tearDownAll(dynamic Function() callback) =>
+    _declarer.tearDownAll(callback);
diff --git a/pkgs/test_core/mono_pkg.yaml b/pkgs/test_core/mono_pkg.yaml
index 995000f..d309ff2 100644
--- a/pkgs/test_core/mono_pkg.yaml
+++ b/pkgs/test_core/mono_pkg.yaml
@@ -6,4 +6,4 @@
       dart: dev
     - group:
       - dartanalyzer: --fatal-warnings .
-      dart: 2.1.0
+      dart: 2.3.0
diff --git a/pkgs/test_core/pubspec.yaml b/pkgs/test_core/pubspec.yaml
index 4f5fe30..da52876 100644
--- a/pkgs/test_core/pubspec.yaml
+++ b/pkgs/test_core/pubspec.yaml
@@ -5,7 +5,7 @@
 homepage: https://github.com/dart-lang/test/blob/master/pkgs/test_core
 
 environment:
-  sdk: ">=2.2.0 <3.0.0"
+  sdk: ">=2.3.0 <3.0.0"
 
 dependencies:
   analyzer: ">=0.36.0 <0.40.0"
diff --git a/tool/travis.sh b/tool/travis.sh
index 099601c..51fad7c 100755
--- a/tool/travis.sh
+++ b/tool/travis.sh
@@ -1,5 +1,28 @@
 #!/bin/bash
-# Created with package:mono_repo v2.1.0
+# Created with package:mono_repo v2.3.0
+
+# Support built in commands on windows out of the box.
+function pub {
+       if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+        command pub.bat "$@"
+    else
+        command pub "$@"
+    fi
+}
+function dartfmt {
+       if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+        command dartfmt.bat "$@"
+    else
+        command dartfmt "$@"
+    fi
+}
+function dartanalyzer {
+       if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+        command dartanalyzer.bat "$@"
+    else
+        command dartanalyzer "$@"
+    fi
+}
 
 if [[ -z ${PKGS} ]]; then
   echo -e '\033[31mPKGS environment variable must be set!\033[0m'
@@ -16,7 +39,16 @@
 for PKG in ${PKGS}; do
   echo -e "\033[1mPKG: ${PKG}\033[22m"
   pushd "${PKG}" || exit $?
-  pub upgrade --no-precompile || exit $?
+
+  PUB_EXIT_CODE=0
+  pub upgrade --no-precompile || PUB_EXIT_CODE=$?
+
+  if [[ ${PUB_EXIT_CODE} -ne 0 ]]; then
+    EXIT_CODE=1
+    echo -e '\033[31mpub upgrade failed\033[0m'
+    popd
+    continue
+  fi
 
   for TASK in "$@"; do
     echo