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>);
}
}