Enable 'strict-inference' language analysis mode (#4018)
diff --git a/analysis_options.yaml b/analysis_options.yaml index f0bd15a..156085c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml
@@ -11,6 +11,7 @@ language: strict-casts: true + strict-inference: true linter: rules:
diff --git a/lib/src/command.dart b/lib/src/command.dart index 49c69ad..b2c5fe3 100644 --- a/lib/src/command.dart +++ b/lib/src/command.dart
@@ -147,7 +147,7 @@ @override String get invocation { PubCommand? command = this; - var names = []; + var names = <String?>[]; do { names.add(command?.name); command = command?.parent as PubCommand?;
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart index 8a0813a..c16e850 100644 --- a/lib/src/command/dependency_services.dart +++ b/lib/src/command/dependency_services.dart
@@ -166,7 +166,7 @@ _UpgradeType.compatible, ), 'singleBreaking': kind != 'transitive' && singleBreakingVersion == null - ? [] + ? <Object>[] : await computeUpgradeSet( singleBreakingVersion, _UpgradeType.singleBreaking, @@ -176,7 +176,7 @@ multiBreakingVersion, _UpgradeType.multiBreaking, ) - : [], + : <Object>[], if (smallestUpgrade != null) 'smallestUpdate': await computeUpgradeSet( smallestUpgrade, @@ -503,7 +503,7 @@ }, ); // Dummy message. - log.message(json.encode({'dependencies': []})); + log.message(json.encode({'dependencies': <Object>[]})); } }
diff --git a/lib/src/error_group.dart b/lib/src/error_group.dart index 8c09552..27a065f 100644 --- a/lib/src/error_group.dart +++ b/lib/src/error_group.dart
@@ -313,7 +313,7 @@ if (_isDone) return; _subscription.cancel(); // Call these asynchronously to work around issue 7913. - Future.value().then((_) { + Future<void>.value().then((_) { _controller.addError(e, stackTrace); _controller.close(); });
diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart index cecf407..4df8f5b 100644 --- a/lib/src/lock_file.dart +++ b/lib/src/lock_file.dart
@@ -420,7 +420,7 @@ /// serialized as absolute. String serialize(String? packageDir, SystemCache cache) { // Convert the dependencies to a simple object. - var packageMap = {}; + var packageMap = <String, Object?>{}; for (final id in packages.values) { packageMap[id.name] = { 'version': id.version.toString(), @@ -432,7 +432,7 @@ } var data = { - 'sdks': mapMap( + 'sdks': mapMap<String, SdkConstraint, String, String>( sdkConstraints, value: (_, constraint) => constraint.effectiveConstraint.toString(), ),
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart index 8131ceb..9c6e1ec 100644 --- a/lib/src/oauth2.dart +++ b/lib/src/oauth2.dart
@@ -124,7 +124,7 @@ // Be sure to save the credentials even when an error happens. _saveCredentials(client.credentials); }); - }).catchError((error) { + }).catchError((Object error) { if (error is _ExpirationException) { log.error("Pub's authorization to upload packages has expired and " "can't be automatically refreshed."); @@ -139,7 +139,7 @@ return withClient(fn); } else { // ignore: only_throw_errors - throw error as Object; + throw error; } }); } @@ -970,7 +970,7 @@ /// /// Throws a [FormatException] if the JSON is incorrectly formatted. factory Credentials.fromJson(String json) { - void validate(bool condition, message) { + void validate(bool condition, String message) { if (condition) return; throw FormatException('Failed to load credentials: $message.\n\n$json'); }
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart index e99ee52..b3062e2 100644 --- a/lib/src/source/hosted.dart +++ b/lib/src/source/hosted.dart
@@ -308,7 +308,7 @@ /// this throws a descriptive FormatException. HostedDescription _parseDescription( String packageName, - description, + Object? description, LanguageVersion languageVersion, ) { if (description == null) {
diff --git a/lib/src/utils.dart b/lib/src/utils.dart index d43780a..ccfb055 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart
@@ -511,7 +511,7 @@ String yamlToString(Object? data) { var buffer = StringBuffer(); - void stringify(bool isMapValue, String indent, data) { + void stringify(bool isMapValue, String indent, Object? data) { // TODO(nweiz): Serialize using the YAML library once it supports // serialization. @@ -757,7 +757,7 @@ final rf = randomizationFactor * (random.nextDouble() * 2 - 1) + 1; final exp = math.min(attempt, 31); // prevent overflows. final delay = delayFactor * math.pow(2.0, exp) * rf; - await Future.delayed(delay < maxDelay ? delay : maxDelay); + await Future<void>.delayed(delay < maxDelay ? delay : maxDelay); } }
diff --git a/test/cache/list_test.dart b/test/cache/list_test.dart index 7b4e5f5..eea83bb 100644 --- a/test/cache/list_test.dart +++ b/test/cache/list_test.dart
@@ -23,7 +23,15 @@ d.dir('hosted', [d.dir('pub.dev', [])]), ]).create(); - await runPub(args: ['cache', 'list'], outputJson: {'packages': {}}); + await runPub( + args: [ + 'cache', + 'list', + ], + outputJson: { + 'packages': <String, Object>{}, + }, + ); }); test('running pub cache list', () async {
diff --git a/test/dependency_services/dependency_services_test.dart b/test/dependency_services/dependency_services_test.dart index 1e307fe..33937b3 100644 --- a/test/dependency_services/dependency_services_test.dart +++ b/test/dependency_services/dependency_services_test.dart
@@ -631,9 +631,11 @@ } dynamic findChangeVersion(dynamic json, String updateType, String name) { - final dep = json['dependencies'].firstWhere((p) => p['name'] == 'foo'); + final dep = + json['dependencies'].firstWhere((dynamic p) => p['name'] == 'foo'); if (dep == null) return null; - return dep[updateType].firstWhere((p) => p['name'] == name)['version']; + return dep[updateType] + .firstWhere((dynamic p) => p['name'] == name)['version']; } class _PackageVersion {
diff --git a/test/embedding/ensure_pubspec_resolved.dart b/test/embedding/ensure_pubspec_resolved.dart index ba46efd..19654be 100644 --- a/test/embedding/ensure_pubspec_resolved.dart +++ b/test/embedding/ensure_pubspec_resolved.dart
@@ -559,7 +559,7 @@ Future _touch(String path) async { // Delay a bit to make sure the modification times are noticeably different. // 1s seems to be the finest granularity that dart:io reports. - await Future.delayed(Duration(seconds: 1)); + await Future<void>.delayed(Duration(seconds: 1)); path = p.join(d.sandbox, 'myapp', path); touch(path);
diff --git a/test/error_group_test.dart b/test/error_group_test.dart index 15ffcf4..ec673bb 100644 --- a/test/error_group_test.dart +++ b/test/error_group_test.dart
@@ -33,9 +33,13 @@ expect(errorGroup.done, throwsFormatException); errorGroup.signalError(FormatException()); - expect(() => errorGroup.registerFuture(Future.value()), throwsStateError); expect( - () => errorGroup.registerStream(StreamController(sync: true).stream), + () => errorGroup.registerFuture(Future<void>.value()), + throwsStateError, + ); + expect( + () => errorGroup + .registerStream(StreamController<void>(sync: true).stream), throwsStateError, ); }); @@ -63,12 +67,14 @@ completer.complete('value'); expect( - completer.future.then((_) => errorGroup.registerFuture(Future.value())), + completer.future + .then((_) => errorGroup.registerFuture(Future<void>.value())), throwsStateError, ); expect( completer.future.then( - (_) => errorGroup.registerStream(StreamController(sync: true).stream), + (_) => errorGroup + .registerStream(StreamController<void>(sync: true).stream), ), throwsStateError, ); @@ -401,7 +407,7 @@ test( "shouldn't throw a top-level exception if a stream receives an error " 'after the other listened stream completes', () { - var signal = Completer(); + var signal = Completer<void>(); expect( stream1.toList().whenComplete(signal.complete), completion(equals(['value1', 'value2'])), @@ -423,7 +429,7 @@ test( "shouldn't throw a top-level exception if an error is signaled after " 'one listened stream completes', () { - var signal = Completer(); + var signal = Completer<void>(); expect( stream1.toList().whenComplete(signal.complete), completion(equals(['value1', 'value2'])), @@ -505,7 +511,7 @@ test( "shouldn't throw a top-level exception if the future receives an " 'error after the listened stream completes', () { - var signal = Completer(); + var signal = Completer<void>(); expect( stream.toList().whenComplete(signal.complete), completion(equals(['value1', 'value2'])),
diff --git a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart index f95db5e..38f32cf 100644 --- a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart +++ b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
@@ -20,7 +20,7 @@ handleUploadForm(globalServer); globalServer.expect('POST', '/upload', (request) async { - await request.read().drain(); + await request.read().drain<void>(); return shelf.Response(200); });
diff --git a/test/lish/cloud_storage_upload_provides_an_error_test.dart b/test/lish/cloud_storage_upload_provides_an_error_test.dart index a11ba95..431e433 100644 --- a/test/lish/cloud_storage_upload_provides_an_error_test.dart +++ b/test/lish/cloud_storage_upload_provides_an_error_test.dart
@@ -20,7 +20,7 @@ handleUploadForm(globalServer); globalServer.expect('POST', '/upload', (request) { - return request.read().drain().then((_) { + return request.read().drain<void>().then((_) { return shelf.Response.notFound( // Actual example of an error code we get from GCS "<?xml version='1.0' encoding='UTF-8'?><Error><Code>EntityTooLarge</Code><Message>Your proposed upload is larger than the maximum object size specified in your Policy Document.</Message><Details>Content-length exceeds upper bound on range</Details></Error>",
diff --git a/test/lish/utils.dart b/test/lish/utils.dart index eebdc37..27df55f 100644 --- a/test/lish/utils.dart +++ b/test/lish/utils.dart
@@ -34,7 +34,7 @@ // that the request body is correctly formatted. See issue 6952. return request .read() - .drain() + .drain<void>() .then((_) => server.url) .then((url) => shelf.Response.found(Uri.parse(url).resolve('/create'))); });
diff --git a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart index 419a81e..0669cb6 100644 --- a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart +++ b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
@@ -32,7 +32,7 @@ var pub = await startPublish(globalServer); globalServer.expect('POST', '/token', (request) { - return request.read().drain().then((_) { + return request.read().drain<void>().then((_) { return shelf.Response( 400, body: jsonEncode({'error': 'invalid_request'}), @@ -46,7 +46,7 @@ await expectLater(pub.stdout, emits(startsWith('Uploading...'))); await authorizePub(pub, globalServer, 'new access token'); - var done = Completer(); + var done = Completer<void>(); globalServer.expect('GET', '/api/packages/versions/new', (request) async { expect( request.headers,
diff --git a/test/test_pub.dart b/test/test_pub.dart index 951ee21..cad7f30 100644 --- a/test/test_pub.dart +++ b/test/test_pub.dart
@@ -79,7 +79,7 @@ Map<String, dynamic> packageSpec(String packageName) => json .decode(File(d.path(packageConfigFilePath)).readAsStringSync())['packages'] .firstWhere( - (e) => e['name'] == packageName, + (dynamic e) => e['name'] == packageName, orElse: () => null, ) as Map<String, dynamic>; @@ -796,7 +796,7 @@ void _validateOutput( List<String> failures, String pipe, - expected, + Object? expected, String actual, ) { if (expected == null) return; @@ -884,7 +884,7 @@ // Remove dart2js's timing logs, which would otherwise cause tests to fail // flakily when compilation takes a long time. actual['log']?.removeWhere( - (entry) => + (dynamic entry) => entry['level'] == 'Fine' && (entry['message'] as String).startsWith('Not yet complete after'), );
diff --git a/test/token/remove_token_test.dart b/test/token/remove_token_test.dart index dd4f4c4..e06459e 100644 --- a/test/token/remove_token_test.dart +++ b/test/token/remove_token_test.dart
@@ -19,7 +19,9 @@ await runPub(args: ['token', 'remove', 'https://server.demo']); - await d.tokensFile({'version': 1, 'hosted': []}).validate(); + await d.tokensFile( + {'version': 1, 'hosted': <Map<String, String>>[]}, + ).validate(); }); test('without any matching schemes, does nothing', () async {
diff --git a/test/token/when_receives_401_removes_token_test.dart b/test/token/when_receives_401_removes_token_test.dart index 13816cc..ad90b33 100644 --- a/test/token/when_receives_401_removes_token_test.dart +++ b/test/token/when_receives_401_removes_token_test.dart
@@ -27,6 +27,8 @@ await pub.shouldExit(65); - await d.tokensFile({'version': 1, 'hosted': []}).validate(); + await d.tokensFile( + {'version': 1, 'hosted': <Map<String, Object?>>[]}, + ).validate(); }); }
diff --git a/test/utils_test.dart b/test/utils_test.dart index 173041d..1ce8869 100644 --- a/test/utils_test.dart +++ b/test/utils_test.dart
@@ -75,7 +75,7 @@ }); test('handles non-string map keys', () { - var map = {}; + var map = <Object?, Object?>{}; map[null] = 'null'; map[123] = 'num'; map[true] = 'bool'; @@ -92,7 +92,7 @@ test('handles empty maps', () { expect(yamlToString({}), equals('{}')); expect( - yamlToString({'a': {}, 'b': {}}), + yamlToString({'a': <Object, Object>{}, 'b': <Object, Object>{}}), equals(''' a: {} b: {}'''), @@ -188,7 +188,7 @@ expect(() => hexEncode([256, 0, 1]), throwsA(isA<FormatException>())); }); test('hexDecode', () { - expect(hexDecode(''), []); + expect(hexDecode(''), <int>[]); expect(hexDecode('ff0001f0abcdef'), [255, 0, 1, 240, 171, 205, 239]); expect(hexDecode('FF0001F0ABCDEF'), [255, 0, 1, 240, 171, 205, 239]); expect(() => hexDecode('F'), throwsA(isA<FormatException>()));
diff --git a/tool/extract_all_pub_dev.dart b/tool/extract_all_pub_dev.dart index ffd08a2..9525a19 100644 --- a/tool/extract_all_pub_dev.dart +++ b/tool/extract_all_pub_dev.dart
@@ -47,7 +47,8 @@ for (final packageName in json['packages'] as Iterable? ?? []) { alreadyDonePackages.add(packageName as String); } - for (final failure in (json['failures'] ?? []) as Iterable) { + for (final failure + in (json['failures'] ?? <Map<String, dynamic>>[]) as Iterable) { failures.add(failure as Map<String, dynamic>); } }