Add strict-cast analysis option (#3919)
diff --git a/.gitignore b/.gitignore
index 89fbed2..d359298 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
.buildlog
.DS_Store
.idea
+.vscode
.dart_tool/
.settings/
/build/
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 85fbba9..4c23fc5 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -9,6 +9,9 @@
exclude:
- lib/src/third_party/**
+ language:
+ strict-casts: true
+
linter:
rules:
- avoid_catching_errors
diff --git a/bin/dependency_services.dart b/bin/dependency_services.dart
index e9d76ac..9fd589d 100644
--- a/bin/dependency_services.dart
+++ b/bin/dependency_services.dart
@@ -16,17 +16,18 @@
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
import 'package:pub/src/log.dart' as log;
+import 'package:pub/src/utils.dart';
class _DependencyServicesCommandRunner extends CommandRunner<int>
implements PubTopLevel {
@override
- String get directory => argResults['directory'];
+ String get directory => argResults.option('directory');
@override
- bool get captureStackChains => argResults['verbose'];
+ bool get captureStackChains => argResults.flag('verbose');
@override
- bool get trace => argResults['verbose'];
+ bool get trace => argResults.flag('verbose');
ArgResults? _argResults;
diff --git a/bin/pub.dart b/bin/pub.dart
old mode 100644
new mode 100755
diff --git a/lib/src/command.dart b/lib/src/command.dart
index b7ee191..2994502 100644
--- a/lib/src/command.dart
+++ b/lib/src/command.dart
@@ -68,7 +68,7 @@
String get directory {
return (argResults.options.contains('directory')
- ? argResults['directory']
+ ? argResults.optionWithoutDefault('directory')
: null) ??
_pubTopLevel.directory;
}
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index 06a0260..b8a23cd 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -766,21 +766,21 @@
}
extension on ArgResults {
- bool get isDev => this['dev'];
- bool get isDryRun => this['dry-run'];
- String? get gitUrl => this['git-url'];
- String? get gitPath => this['git-path'];
- String? get gitRef => this['git-ref'];
- String? get hostedUrl => this['hosted-url'];
- String? get path => this['path'];
- String? get sdk => this['sdk'];
+ bool get isDev => flag('dev');
+ bool get isDryRun => flag('dry-run');
+ String? get gitUrl => this['git-url'] as String?;
+ String? get gitPath => this['git-path'] as String?;
+ String? get gitRef => this['git-ref'] as String?;
+ String? get hostedUrl => this['hosted-url'] as String?;
+ String? get path => this['path'] as String?;
+ String? get sdk => this['sdk'] as String?;
bool get hasOldStyleOptions =>
hasGitOptions ||
path != null ||
sdk != null ||
hostedUrl != null ||
isDev;
- bool get shouldPrecompile => this['precompile'];
- bool get example => this['example'];
+ bool get shouldPrecompile => flag('precompile');
+ bool get example => flag('example');
bool get hasGitOptions => gitUrl != null || gitRef != null || gitPath != null;
}
diff --git a/lib/src/command/cache_add.dart b/lib/src/command/cache_add.dart
index 85c2c5d..25508ec 100644
--- a/lib/src/command/cache_add.dart
+++ b/lib/src/command/cache_add.dart
@@ -8,6 +8,7 @@
import '../command.dart';
import '../log.dart' as log;
+import '../package_name.dart';
import '../utils.dart';
/// Handles the `cache add` pub command.
@@ -52,7 +53,7 @@
var constraint = VersionConstraint.any;
if (argResults['version'] != null) {
try {
- constraint = VersionConstraint.parse(argResults['version']);
+ constraint = VersionConstraint.parse(argResults['version'] as String);
} on FormatException catch (error) {
usageException(error.message);
}
@@ -71,14 +72,14 @@
fail('Package $package has no versions that match $constraint.');
}
- Future<void> downloadVersion(id) async {
+ Future<void> downloadVersion(PackageId id) async {
final result = await cache.downloadPackage(id);
if (!result.didUpdate) {
log.message('Already cached ${id.name} ${id.version}.');
}
}
- if (argResults['all']) {
+ if (argResults.flag('all')) {
// Install them in ascending order.
ids.sort((id1, id2) => id1.version.compareTo(id2.version));
await Future.forEach(ids, downloadVersion);
diff --git a/lib/src/command/cache_clean.dart b/lib/src/command/cache_clean.dart
index 786707d..d981b1f 100644
--- a/lib/src/command/cache_clean.dart
+++ b/lib/src/command/cache_clean.dart
@@ -6,6 +6,7 @@
import '../command_runner.dart';
import '../io.dart';
import '../log.dart' as log;
+import '../utils.dart';
class CacheCleanCommand extends PubCommand {
@override
@@ -27,7 +28,7 @@
@override
Future<void> runProtected() async {
if (dirExists(cache.rootDir)) {
- if (argResults['force'] || await confirm('''
+ if (argResults.flag('force') || await confirm('''
This will remove everything inside ${cache.rootDir}.
You will have to run `$topLevelProgram pub get` again in each project.
Are you sure?''')) {
diff --git a/lib/src/command/cache_repair.dart b/lib/src/command/cache_repair.dart
index 1c3cd8c..b0e0b04 100644
--- a/lib/src/command/cache_repair.dart
+++ b/lib/src/command/cache_repair.dart
@@ -38,13 +38,15 @@
if (successes.isNotEmpty) {
var packages = pluralize('package', successes.length);
- log.message('Reinstalled ${log.green(successes.length)} $packages.');
+ log.message(
+ 'Reinstalled ${log.green(successes.length.toString())} $packages.',
+ );
}
if (failures.isNotEmpty) {
var packages = pluralize('package', failures.length);
var buffer = StringBuffer(
- 'Failed to reinstall ${log.red(failures.length)} $packages:\n',
+ 'Failed to reinstall ${log.red(failures.length.toString())} $packages:\n',
);
for (var failure in failures) {
@@ -62,14 +64,14 @@
if (globalRepairResults.first.isNotEmpty) {
var packages = pluralize('package', globalRepairResults.first.length);
log.message(
- 'Reactivated ${log.green(globalRepairResults.first.length)} $packages.',
+ 'Reactivated ${log.green(globalRepairResults.first.length.toString())} $packages.',
);
}
if (globalRepairResults.last.isNotEmpty) {
var packages = pluralize('package', globalRepairResults.last.length);
log.message(
- 'Failed to reactivate ${log.red(globalRepairResults.last.length)} $packages:',
+ 'Failed to reactivate ${log.red(globalRepairResults.last.length.toString())} $packages:',
);
log.message(
globalRepairResults.last
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index ced8c00..44ae700 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -69,8 +69,10 @@
} else {
final resolution = await _tryResolve(entrypoint.root.pubspec, cache) ??
(throw DataException('Failed to resolve pubspec'));
- currentPackages =
- Map<String, PackageId>.fromIterable(resolution, key: (e) => e.name);
+ currentPackages = Map<String, PackageId>.fromIterable(
+ resolution,
+ key: (e) => (e as PackageId).name,
+ );
}
currentPackages.remove(entrypoint.root.name);
@@ -361,13 +363,13 @@
YamlEditor(readTextFile(entrypoint.pubspecPath));
final toApply = <_PackageVersion>[];
final input = json.decode(await utf8.decodeStream(stdin));
- for (final change in input['dependencyChanges']) {
+ for (final change in input['dependencyChanges'] as Iterable) {
toApply.add(
_PackageVersion(
- change['name'],
- change['version'],
+ change['name'] as String,
+ change['version'] as String?,
change['constraint'] != null
- ? VersionConstraint.parse(change['constraint'])
+ ? VersionConstraint.parse(change['constraint'] as String)
: null,
),
);
@@ -421,23 +423,23 @@
}
if (lockFileEditor != null) {
if (targetVersion != null &&
- lockFileYaml['packages'].containsKey(targetPackage)) {
+ (lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
lockFileEditor.update(
['packages', targetPackage, 'version'],
targetVersion.toString(),
);
// Remove the now outdated content-hash - it will be restored below
// after resolution.
- if (lockFileEditor
- .parseAt(['packages', targetPackage, 'description'])
- .value
- .containsKey('sha256')) {
+ var packageMap = lockFileEditor
+ .parseAt(['packages', targetPackage, 'description']).value as Map;
+ var hasSha = packageMap.containsKey('sha256');
+ if (hasSha) {
lockFileEditor.remove(
['packages', targetPackage, 'description', 'sha256'],
);
}
} else if (targetRevision != null &&
- lockFileYaml['packages'].containsKey(targetPackage)) {
+ (lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
final ref = entrypoint.lockFile.packages[targetPackage]!.toRef();
final currentDescription = ref.description as GitDescription;
final updatedRef = PackageRef(
@@ -468,7 +470,7 @@
);
} else if (targetVersion == null &&
targetRevision == null &&
- !lockFileYaml['packages'].containsKey(targetPackage)) {
+ !(lockFileYaml['packages'] as Map).containsKey(targetPackage)) {
dataError(
'Trying to remove non-existing transitive dependency $targetPackage.',
);
diff --git a/lib/src/command/deps.dart b/lib/src/command/deps.dart
index 0fe86c2..a3e2be8 100644
--- a/lib/src/command/deps.dart
+++ b/lib/src/command/deps.dart
@@ -32,7 +32,7 @@
bool get takesArguments => false;
/// Whether to include dev dependencies.
- bool get _includeDev => argResults['dev'];
+ bool get _includeDev => argResults.flag('dev');
DepsCommand() {
argParser.addOption(
@@ -75,7 +75,7 @@
await entrypoint.ensureUpToDate();
final buffer = StringBuffer();
- if (argResults['json']) {
+ if (argResults.flag('json')) {
if (argResults.wasParsed('dev')) {
usageException(
'Cannot combine --json and --dev.\nThe json output contains the dependency type in the output.',
@@ -150,7 +150,7 @@
),
);
} else {
- if (argResults['executables']) {
+ if (argResults.flag('executables')) {
_outputExecutables(buffer);
} else {
for (var sdk in sdks.values) {
@@ -174,7 +174,7 @@
}
}
- log.message(buffer);
+ log.message(buffer.toString());
}
/// Outputs a list of all of the package's immediate, dev, override, and
diff --git a/lib/src/command/downgrade.dart b/lib/src/command/downgrade.dart
index e92b894..8c7a17d 100644
--- a/lib/src/command/downgrade.dart
+++ b/lib/src/command/downgrade.dart
@@ -7,6 +7,7 @@
import '../command.dart';
import '../log.dart' as log;
import '../solver.dart';
+import '../utils.dart';
/// Handles the `downgrade` pub command.
class DowngradeCommand extends PubCommand {
@@ -21,7 +22,7 @@
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-downgrade';
@override
- bool get isOffline => argResults['offline'];
+ bool get isOffline => argResults.flag('offline');
DowngradeCommand() {
argParser.addFlag(
@@ -62,7 +63,7 @@
),
);
}
- var dryRun = argResults['dry-run'];
+ var dryRun = argResults.flag('dry-run');
await entrypoint.acquireDependencies(
SolveType.downgrade,
@@ -71,7 +72,7 @@
analytics: analytics,
);
var example = entrypoint.example;
- if (argResults['example'] && example != null) {
+ if (argResults.flag('example') && example != null) {
await example.acquireDependencies(
SolveType.get,
unlock: argResults.rest,
diff --git a/lib/src/command/get.dart b/lib/src/command/get.dart
index 51419c1..2544282 100644
--- a/lib/src/command/get.dart
+++ b/lib/src/command/get.dart
@@ -7,6 +7,7 @@
import '../command.dart';
import '../log.dart' as log;
import '../solver.dart';
+import '../utils.dart';
/// Handles the `get` pub command.
class GetCommand extends PubCommand {
@@ -17,7 +18,7 @@
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-get';
@override
- bool get isOffline => argResults['offline'];
+ bool get isOffline => argResults.flag('offline');
@override
String get argumentsDescription => '';
@@ -75,21 +76,21 @@
await entrypoint.acquireDependencies(
SolveType.get,
- dryRun: argResults['dry-run'],
- precompile: argResults['precompile'],
+ dryRun: argResults.flag('dry-run'),
+ precompile: argResults.flag('precompile'),
analytics: analytics,
- enforceLockfile: argResults['enforce-lockfile'],
+ enforceLockfile: argResults.flag('enforce-lockfile'),
);
var example = entrypoint.example;
- if (argResults['example'] && example != null) {
+ if ((argResults['example'] as bool? ?? false) && example != null) {
await example.acquireDependencies(
SolveType.get,
- dryRun: argResults['dry-run'],
- precompile: argResults['precompile'],
+ dryRun: argResults.flag('dry-run'),
+ precompile: argResults.flag('precompile'),
analytics: analytics,
summaryOnly: true,
- enforceLockfile: argResults['enforce-lockfile'],
+ enforceLockfile: argResults.flag('enforce-lockfile'),
);
}
}
diff --git a/lib/src/command/global_activate.dart b/lib/src/command/global_activate.dart
index 8fdbc46..2080894 100644
--- a/lib/src/command/global_activate.dart
+++ b/lib/src/command/global_activate.dart
@@ -87,8 +87,8 @@
usageException('Cannot pass both --no-executables and --executable.');
}
- executables = argResults['executable'];
- } else if (argResults['no-executables']) {
+ executables = argResults['executable'] as List<String>?;
+ } else if (argResults.flag('no-executables')) {
// An empty list means no executables.
executables = [];
}
@@ -126,8 +126,8 @@
repo,
executables,
overwriteBinStubs: overwrite,
- path: argResults['git-path'],
- ref: argResults['git-ref'],
+ path: argResults['git-path'] as String?,
+ ref: argResults['git-ref'] as String?,
);
case 'hosted':
@@ -135,7 +135,8 @@
PackageRef ref;
try {
- ref = cache.hosted.refFor(package, url: argResults['hosted-url']);
+ ref = cache.hosted
+ .refFor(package, url: argResults['hosted-url'] as String?);
} on FormatException catch (e) {
usageException('Invalid hosted-url: $e');
}
diff --git a/lib/src/command/global_run.dart b/lib/src/command/global_run.dart
index c7e615b..c6e996f 100644
--- a/lib/src/command/global_run.dart
+++ b/lib/src/command/global_run.dart
@@ -79,7 +79,8 @@
Executable.adaptProgramName(package, executable),
args,
vmArgs: vmArgs,
- enableAsserts: argResults['enable-asserts'] || argResults['checked'],
+ enableAsserts:
+ argResults.flag('enable-asserts') || argResults.flag('checked'),
recompile: (executable) => log.errorsOnlyUnlessTerminal(
() => globalEntrypoint.precompileExecutable(executable),
),
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 294df13..9c4372c 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -40,7 +40,7 @@
// An explicit argument takes precedence.
if (argResults.wasParsed('server')) {
try {
- return validateAndNormalizeHostedUrl(argResults['server']);
+ return validateAndNormalizeHostedUrl(argResults.option('server'));
} on FormatException catch (e) {
usageException('Invalid server: $e');
}
@@ -61,12 +61,12 @@
}();
/// Whether the publish is just a preview.
- bool get dryRun => argResults['dry-run'];
+ bool get dryRun => argResults.flag('dry-run');
/// Whether the publish requires confirmation.
- bool get force => argResults['force'];
+ bool get force => argResults.flag('force');
- bool get skipValidation => argResults['skip-validation'];
+ bool get skipValidation => argResults.flag('skip-validation');
LishCommand() {
argParser.addFlag(
@@ -134,7 +134,7 @@
if (fields is! Map) invalidServerResponse(parametersResponse);
fields.forEach((key, value) {
if (value is! String) invalidServerResponse(parametersResponse);
- request.fields[key] = value;
+ request.fields[key as String] = value;
});
request.followRedirects = false;
diff --git a/lib/src/command/login.dart b/lib/src/command/login.dart
index 670d1a8..68ec850 100644
--- a/lib/src/command/login.dart
+++ b/lib/src/command/login.dart
@@ -47,11 +47,17 @@
return await oauth2.withClient((client) async {
final discovery = await oauth2.fetchOidcDiscoveryDocument();
final userInfoEndpoint = discovery['userinfo_endpoint'];
+ if (userInfoEndpoint is! String) {
+ log.fine(
+ 'Bad discovery document. userinfo_endpoint not a String',
+ );
+ return null;
+ }
final userInfoRequest = await client.get(Uri.parse(userInfoEndpoint));
if (userInfoRequest.statusCode != 200) return null;
try {
final userInfo = json.decode(userInfoRequest.body);
- final name = userInfo['name'];
+ final name = userInfo['name'] as String?;
final email = userInfo['email'];
if (email is String) {
return _UserInfo(name, email);
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index dee80a1..050cedc 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -39,7 +39,8 @@
/// Avoid showing spinning progress messages when not in a terminal, and
/// when we are outputting machine-readable json.
- bool get _shouldShowSpinner => terminalOutputForStdout && !argResults['json'];
+ bool get _shouldShowSpinner =>
+ terminalOutputForStdout && !argResults.flag('json');
@override
bool get takesArguments => false;
@@ -118,9 +119,9 @@
}
final mode = _OutdatedMode();
- final includeDevDependencies = argResults['dev-dependencies'];
- final includeDependencyOverrides = argResults['dependency-overrides'];
- if (argResults['json'] && argResults.wasParsed('transitive')) {
+ final includeDevDependencies = argResults.flag('dev-dependencies');
+ final includeDependencyOverrides = argResults.flag('dependency-overrides');
+ if (argResults.flag('json') && argResults.wasParsed('transitive')) {
usageException('Cannot specify both `--json` and `--transitive`\n'
'The json report always includes transitive dependencies.');
}
@@ -288,8 +289,9 @@
rows.sort();
- final showAll = argResults['show-all'] || argResults['up-to-date'];
- if (argResults['json']) {
+ final showAll =
+ argResults.flag('show-all') || argResults.flag('up-to-date');
+ if (argResults.flag('json')) {
await _outputJson(
rows,
mode,
@@ -321,7 +323,7 @@
}
bool get showTransitiveDependencies {
- return argResults['transitive'];
+ return argResults.flag('transitive');
}
late final bool prereleases = () {
@@ -330,10 +332,10 @@
// 'pre-releases'.
// Otherwise fall back to the default implied by the mode.
if (argResults.wasParsed('prereleases')) {
- return argResults['prereleases'];
+ return argResults.flag('prereleases');
}
if (argResults.wasParsed('pre-releases')) {
- return argResults['pre-releases'];
+ return argResults.flag('pre-releases');
}
return false;
}();
@@ -365,10 +367,7 @@
Package root,
Iterable<PackageId> resolution,
) async {
- final nameToId = Map<String, PackageId>.fromIterable(
- resolution,
- key: (id) => id.name,
- );
+ final nameToId = {for (final id in resolution) id.name: id};
final nonDevDependencies = <String>{root.name};
final queue = [...root.dependencies.keys];
@@ -865,7 +864,7 @@
_FormattedString _format(
String value,
String Function(String) format, {
- prefix = '',
+ String? prefix = '',
}) {
return _FormattedString(value, format: format, prefix: prefix);
}
@@ -887,10 +886,10 @@
_MarkedVersionDetails(
this._versionDetails, {
required this.asDesired,
- format,
- prefix = '',
- suffix = '',
- jsonExplanation,
+ String Function(String)? format,
+ String? prefix = '',
+ String? suffix = '',
+ MapEntry<String, Object>? jsonExplanation,
}) : _format = format,
_prefix = prefix,
_suffix = suffix,
@@ -927,8 +926,8 @@
_FormattedString(
this.value, {
String Function(String)? format,
- prefix,
- suffix,
+ String? prefix,
+ String? suffix,
}) : _format = format ?? _noFormat,
_prefix = prefix ?? '',
_suffix = suffix ?? '';
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index a367588..7063c52 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -10,6 +10,7 @@
import '../log.dart' as log;
import '../pubspec.dart';
import '../solver.dart';
+import '../utils.dart';
/// Handles the `remove` pub command. Removes dependencies from `pubspec.yaml`,
/// and performs an operation similar to `pub get`. Unlike `pub add`, this
@@ -33,9 +34,9 @@
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-remove';
@override
- bool get isOffline => argResults['offline'];
+ bool get isOffline => argResults.flag('offline');
- bool get isDryRun => argResults['dry-run'];
+ bool get isDryRun => argResults.flag('dry-run');
RemoveCommand() {
argParser.addFlag(
@@ -92,16 +93,16 @@
await entrypoint.withPubspec(newPubspec).acquireDependencies(
SolveType.get,
- precompile: !isDryRun && argResults['precompile'],
+ precompile: !isDryRun && argResults.flag('precompile'),
dryRun: isDryRun,
analytics: isDryRun ? null : analytics,
);
var example = entrypoint.example;
- if (!isDryRun && argResults['example'] && example != null) {
+ if (!isDryRun && argResults.flag('example') && example != null) {
await example.acquireDependencies(
SolveType.get,
- precompile: argResults['precompile'],
+ precompile: argResults.flag('precompile'),
summaryOnly: true,
analytics: analytics,
);
diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart
index 67920e1..9fe1a03 100644
--- a/lib/src/command/run.dart
+++ b/lib/src/command/run.dart
@@ -101,7 +101,8 @@
entrypoint,
Executable.adaptProgramName(package, executable),
args,
- enableAsserts: argResults['enable-asserts'] || argResults['checked'],
+ enableAsserts:
+ argResults.flag('enable-asserts') || argResults.flag('checked'),
recompile: (executable) => log.errorsOnlyUnlessTerminal(
() => entrypoint.precompileExecutable(executable),
),
diff --git a/lib/src/command/token_add.dart b/lib/src/command/token_add.dart
index 5ade7ba..c15a51e 100644
--- a/lib/src/command/token_add.dart
+++ b/lib/src/command/token_add.dart
@@ -37,7 +37,7 @@
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-token';
- String? get envVar => argResults['env-var'];
+ String? get envVar => argResults['env-var'] as String?;
TokenAddCommand() {
argParser.addOption(
diff --git a/lib/src/command/token_list.dart b/lib/src/command/token_list.dart
index 178d0a4..61b797f 100644
--- a/lib/src/command/token_list.dart
+++ b/lib/src/command/token_list.dart
@@ -22,7 +22,7 @@
'repositories:',
);
for (final token in cache.tokenStore.credentials) {
- log.message(token.url);
+ log.message(token.url.toString());
}
} else {
log.message(
diff --git a/lib/src/command/token_remove.dart b/lib/src/command/token_remove.dart
index b4a9a77..f3f20c0 100644
--- a/lib/src/command/token_remove.dart
+++ b/lib/src/command/token_remove.dart
@@ -6,6 +6,7 @@
import '../exceptions.dart';
import '../log.dart' as log;
import '../source/hosted.dart';
+import '../utils.dart';
/// Handles the `token remove` pub command.
class TokenRemoveCommand extends PubCommand {
@@ -19,7 +20,7 @@
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-token';
- bool get isAll => argResults['all'];
+ bool get isAll => argResults.flag('all');
TokenRemoveCommand() {
argParser.addFlag(
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index 6c1dcda..bbe28ef 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -35,7 +35,7 @@
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-upgrade';
@override
- bool get isOffline => argResults['offline'];
+ bool get isOffline => argResults.flag('offline');
UpgradeCommand() {
argParser.addFlag(
@@ -90,14 +90,14 @@
/// Avoid showing spinning progress messages when not in a terminal.
bool get _shouldShowSpinner => terminalOutputForStdout;
- bool get _dryRun => argResults['dry-run'];
+ bool get _dryRun => argResults.flag('dry-run');
- bool get _precompile => argResults['precompile'];
+ bool get _precompile => argResults.flag('precompile');
bool get _upgradeNullSafety =>
- argResults['nullsafety'] || argResults['null-safety'];
+ argResults.flag('nullsafety') || argResults.flag('null-safety');
- bool get _upgradeMajorVersions => argResults['major-versions'];
+ bool get _upgradeMajorVersions => argResults.flag('major-versions');
@override
Future<void> runProtected() async {
@@ -114,7 +114,7 @@
}
if (_upgradeMajorVersions) {
- if (argResults['example'] && entrypoint.example != null) {
+ if (argResults.flag('example') && entrypoint.example != null) {
log.warning(
'Running `upgrade --major-versions` only in `${entrypoint.rootDir}`. Run `$topLevelProgram pub upgrade --major-versions --directory example/` separately.',
);
@@ -123,7 +123,7 @@
} else {
await _runUpgrade(entrypoint);
}
- if (argResults['example'] && entrypoint.example != null) {
+ if (argResults.flag('example') && entrypoint.example != null) {
// Reload the entrypoint to ensure we pick up potential changes that has
// been made.
final exampleEntrypoint = Entrypoint(directory, cache).example!;
diff --git a/lib/src/command/uploader.dart b/lib/src/command/uploader.dart
index 28ff85d..e661d72 100644
--- a/lib/src/command/uploader.dart
+++ b/lib/src/command/uploader.dart
@@ -23,7 +23,7 @@
bool get hidden => true;
/// The URL of the package hosting server.
- Uri get server => Uri.parse(argResults['server']);
+ Uri get server => Uri.parse(argResults.option('server'));
UploaderCommand() {
argParser.addOption(
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index 5fa9344..f9687fe 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -32,6 +32,7 @@
import 'log.dart' as log;
import 'log.dart';
import 'sdk.dart';
+import 'utils.dart';
/// The name of the program that is invoking pub
/// 'flutter' if we are running inside `flutter pub` 'dart' otherwise.
@@ -42,13 +43,13 @@
class PubCommandRunner extends CommandRunner<int> implements PubTopLevel {
@override
- String get directory => argResults['directory'];
+ String get directory => argResults.option('directory');
@override
bool get captureStackChains {
- return argResults['trace'] ||
- argResults['verbose'] ||
- argResults['verbosity'] == 'all';
+ return argResults.flag('trace') ||
+ argResults.flag('verbose') ||
+ argResults.optionWithoutDefault('verbosity') == 'all';
}
@override
@@ -68,14 +69,14 @@
return log.Verbosity.all;
default:
// No specific verbosity given, so check for the shortcut.
- if (argResults['verbose']) return log.Verbosity.all;
+ if (argResults.flag('verbose')) return log.Verbosity.all;
if (runningFromTest) return log.Verbosity.testing;
return log.Verbosity.normal;
}
}
@override
- bool get trace => argResults['trace'];
+ bool get trace => argResults.flag('trace');
ArgResults? _argResults;
@@ -170,7 +171,7 @@
Future<int?> runCommand(ArgResults topLevelResults) async {
_checkDepsSynced();
- if (topLevelResults['version']) {
+ if (topLevelResults.flag('version')) {
log.message('Pub ${sdk.version}');
return 0;
}
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index ab8fed6..cb1ecee 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -148,7 +148,7 @@
}
late PackageConfig result;
try {
- result = PackageConfig.fromJson(json.decode(packageConfigRaw));
+ result = PackageConfig.fromJson(json.decode(packageConfigRaw) as Object?);
} on FormatException {
badPackageConfig();
}
diff --git a/lib/src/error_group.dart b/lib/src/error_group.dart
index 560d806..8c09552 100644
--- a/lib/src/error_group.dart
+++ b/lib/src/error_group.dart
@@ -106,7 +106,7 @@
///
/// If all members of [this] have already completed successfully or with an
/// error, it's a [StateError] to try to signal an error.
- void signalError(var error, [StackTrace? stackTrace]) {
+ void signalError(Object error, [StackTrace? stackTrace]) {
if (_isDone) {
throw StateError("Can't signal errors on a complete ErrorGroup.");
}
@@ -118,7 +118,7 @@
///
/// This is just like [signalError], but instead of throwing an error if
/// [this] is complete, it just does nothing.
- void _signalError(var error, [StackTrace? stackTrace]) {
+ void _signalError(Object error, [StackTrace? stackTrace]) {
if (_isDone) return;
var caught = false;
@@ -136,6 +136,7 @@
_done._signalError(error, stackTrace);
if (!caught && !_done._hasListeners) {
scheduleMicrotask(() {
+ // ignore: only_throw_errors
throw error;
});
}
@@ -234,7 +235,7 @@
/// Signal that an error from [_group] should be propagated through [this],
/// unless it's already complete.
- void _signalError(var error, [StackTrace? stackTrace]) {
+ void _signalError(Object error, [StackTrace? stackTrace]) {
if (!_isDone) _completer.completeError(error, stackTrace);
_isDone = true;
}
@@ -308,7 +309,7 @@
/// Signal that an error from [_group] should be propagated through [this],
/// unless it's already complete.
- void _signalError(var e, [StackTrace? stackTrace]) {
+ void _signalError(Object e, [StackTrace? stackTrace]) {
if (_isDone) return;
_subscription.cancel();
// Call these asynchronously to work around issue 7913.
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 5ed3438..b9b25b6 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -615,7 +615,7 @@
message.writeln(' From ${log.bold(package)}: '
'${toSentence(executableNames)}');
});
- log.error(message);
+ log.error(message.toString());
}
return Pair(successes, failures);
diff --git a/lib/src/http.dart b/lib/src/http.dart
index ab302fd..732381d 100644
--- a/lib/src/http.dart
+++ b/lib/src/http.dart
@@ -178,13 +178,14 @@
/// "some message"}}`. If the format is correct, the message will be printed;
/// otherwise an error will be raised.
void handleJsonSuccess(http.Response response) {
- var parsed = parseJsonResponse(response);
- if (parsed['success'] is! Map ||
- !parsed['success'].containsKey('message') ||
+ final parsed = parseJsonResponse(response);
+ final success = parsed['success'];
+ if (success is! Map ||
+ !(parsed['success'] as Map).containsKey('message') ||
parsed['success']['message'] is! String) {
invalidServerResponse(response);
}
- log.message(log.green(parsed['success']['message']));
+ log.message(log.green(parsed['success']['message'] as String));
}
/// Handles an unsuccessful JSON-formatted response from pub.dev.
@@ -199,12 +200,13 @@
fail(log.red('Invalid server response'));
}
var errorMap = parseJsonResponse(response);
- if (errorMap['error'] is! Map ||
- !errorMap['error'].containsKey('message') ||
- errorMap['error']['message'] is! String) {
+ final error = errorMap['error'];
+ if (error is! Map ||
+ !error.containsKey('message') ||
+ error['message'] is! String) {
invalidServerResponse(response);
}
- fail(log.red(errorMap['error']['message']));
+ fail(log.red(error['message'] as String));
}
/// Parses a response body, assuming it's JSON-formatted.
@@ -212,9 +214,9 @@
/// Throws a user-friendly error if the response body is invalid JSON, or if
/// it's not a map.
Map parseJsonResponse(http.Response response) {
- Object value;
+ Object? value;
try {
- value = jsonDecode(response.body);
+ value = jsonDecode(response.body) as Object?;
} on FormatException {
invalidServerResponse(response);
}
diff --git a/lib/src/io.dart b/lib/src/io.dart
index 086f93f..386d176 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -742,7 +742,7 @@
Future<PubProcessResult> runProcess(
String executable,
List<String> args, {
- workingDir,
+ String? workingDir,
Map<String, String>? environment,
bool runInShell = false,
}) {
@@ -765,8 +765,11 @@
);
}
- var pubResult =
- PubProcessResult(result.stdout, result.stderr, result.exitCode);
+ var pubResult = PubProcessResult(
+ result.stdout as String,
+ result.stderr as String,
+ result.exitCode,
+ );
log.processResult(executable, pubResult);
return pubResult;
});
@@ -833,8 +836,11 @@
} on IOException catch (e) {
throw RunProcessException('Pub failed to run subprocess `$executable`: $e');
}
- var pubResult =
- PubProcessResult(result.stdout, result.stderr, result.exitCode);
+ var pubResult = PubProcessResult(
+ result.stdout as String,
+ result.stderr as String,
+ result.exitCode,
+ );
log.processResult(executable, pubResult);
return pubResult;
}
diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart
index 48de2fd..b7fe219 100644
--- a/lib/src/lock_file.dart
+++ b/lib/src/lock_file.dart
@@ -55,10 +55,10 @@
Set<String>? devDependencies,
Set<String>? overriddenDependencies,
}) : this._(
- Map.fromIterable(
- ids.where((id) => !id.isRoot),
- key: (id) => id.name,
- ),
+ {
+ for (final id in ids)
+ if (!id.isRoot) id.name: id
+ },
sdkConstraints ?? {'dart': SdkConstraint(VersionConstraint.any)},
mainDependencies ?? const UnmodifiableSetView.empty(),
devDependencies ?? const UnmodifiableSetView.empty(),
@@ -289,7 +289,7 @@
return _wrapFormatException(
'Expected a $typeDescription',
node.span,
- () => parse(node.value),
+ () => parse(value),
);
} else if (value is T) {
return value;
@@ -307,7 +307,7 @@
) {
map.nodes.forEach((key, value) {
f(
- _parseNode(key, keyTypeDescription),
+ _parseNode(key as YamlNode, keyTypeDescription),
_parseNode(value, valueTypeDescription),
);
});
diff --git a/lib/src/log.dart b/lib/src/log.dart
index 5a1299d..9bc467f 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -204,33 +204,32 @@
///
/// If [error] is passed, it's appended to [message]. If [trace] is passed, it's
/// printed at log level fine.
-void error(message, [error, StackTrace? trace]) {
- message ??= '';
+void error(String message, [error, StackTrace? trace]) {
if (error != null) {
message = message.isEmpty ? '$error' : '$message: $error';
if (error is Error && trace == null) trace = error.stackTrace;
}
write(Level.error, message);
- if (trace != null) write(Level.fine, Chain.forTrace(trace));
+ if (trace != null) write(Level.fine, Chain.forTrace(trace).toString());
}
/// Logs [message] at [Level.warning].
-void warning(message) => write(Level.warning, message);
+void warning(String message) => write(Level.warning, message);
/// Logs [message] at [Level.message].
-void message(message) => write(Level.message, message);
+void message(String message) => write(Level.message, message);
/// Logs [message] at [Level.io].
-void io(message) => write(Level.io, message);
+void io(String message) => write(Level.io, message);
/// Logs [message] at [Level.solver].
-void solver(message) => write(Level.solver, message);
+void solver(String message) => write(Level.solver, message);
/// Logs [message] at [Level.fine].
-void fine(message) => write(Level.fine, message);
+void fine(String message) => write(Level.fine, message);
/// Logs [message] at [level].
-void write(Level level, message) {
+void write(Level level, String message) {
message = message.toString();
var lines = splitLines(message);
@@ -290,7 +289,7 @@
}
/// Logs an exception.
-void exception(exception, [StackTrace? trace]) {
+void exception(Object exception, [StackTrace? trace]) {
if (exception is SilentException) return;
var chain = trace == null ? Chain.current() : Chain.forTrace(trace);
@@ -314,9 +313,9 @@
}
if (!isUserFacingException(exception)) {
- error(chain.terse);
+ error(chain.terse.toString());
} else {
- fine(chain.terse);
+ fine(chain.terse.toString());
}
if (exception is WrappedException && exception.innerError != null) {
@@ -505,38 +504,38 @@
/// that supports that.
///
/// Use this to highlight something interesting but neither good nor bad.
-String cyan(text) => _addColor(text, _cyan);
+String cyan(String text) => _addColor(text, _cyan);
/// Wraps [text] in the ANSI escape codes to color it green when on a platform
/// that supports that.
///
/// Use this to highlight something successful or otherwise positive.
-String green(text) => _addColor(text, _green);
+String green(String text) => _addColor(text, _green);
/// Wraps [text] in the ANSI escape codes to color it magenta when on a
/// platform that supports that.
///
/// Use this to highlight something risky that the user should be aware of but
/// may intend to do.
-String magenta(text) => _addColor(text, _magenta);
+String magenta(String text) => _addColor(text, _magenta);
/// Wraps [text] in the ANSI escape codes to color it red when on a platform
/// that supports that.
///
/// Use this to highlight unequivocal errors, problems, or failures.
-String red(text) => _addColor(text, _red);
+String red(String text) => _addColor(text, _red);
/// Wraps [text] in the ANSI escape codes to color it yellow when on a platform
/// that supports that.
///
/// Use this to highlight warnings, cautions or other things that are bad but
/// do not prevent the user's goal from being reached.
-String yellow(text) => _addColor(text, _yellow);
+String yellow(String text) => _addColor(text, _yellow);
/// Returns [text] colored using the given [colorCode].
///
/// This is resilient to the text containing other colors or bold text.
-String _addColor(Object text, String colorCode) {
+String _addColor(String text, String colorCode) {
return colorCode +
text
.toString()
@@ -603,7 +602,7 @@
/// is enabled.
///
/// Always prints to stdout.
- void error(error, [stackTrace]) {
+ void error(Object error, [StackTrace? stackTrace]) {
var errorJson = {'error': error.toString()};
if (stackTrace == null && error is Error) stackTrace = error.stackTrace;
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart
index d4053f8..d4d88c9 100644
--- a/lib/src/oauth2.dart
+++ b/lib/src/oauth2.dart
@@ -135,7 +135,8 @@
_clearCredentials();
return withClient(fn);
} else {
- throw error;
+ // ignore: only_throw_errors
+ throw error as Object;
}
});
}
@@ -226,7 +227,7 @@
// Spin up a one-shot HTTP server to receive the authorization code from the
// Google OAuth2 server via redirect. This server will close itself as soon as
// the code is received.
- var completer = Completer();
+ var completer = Completer<Client>();
var server = await bindServer('localhost', 0);
shelf_io.serveRequests(server, (request) {
if (request.url.path.isNotEmpty) {
diff --git a/lib/src/package_config.dart b/lib/src/package_config.dart
index b215555..2123a4d 100644
--- a/lib/src/package_config.dart
+++ b/lib/src/package_config.dart
@@ -56,13 +56,13 @@
///
/// Throws [FormatException], if format is invalid, this does not validate the
/// contents only that the format is correct.
- factory PackageConfig.fromJson(Object data) {
+ factory PackageConfig.fromJson(Object? data) {
if (data is! Map<String, dynamic>) {
throw FormatException('package_config.json must be a JSON object');
}
final root = data;
- void throwFormatException(String property, String mustBe) =>
+ Never throwFormatException(String property, String mustBe) =>
throw FormatException(
'"$property" in .dart_tool/package_config.json $mustBe',
);
@@ -85,7 +85,7 @@
}
final packages = <PackageConfigEntry>[];
for (final entry in packagesRaw) {
- packages.add(PackageConfigEntry.fromJson(entry));
+ packages.add(PackageConfigEntry.fromJson(entry as Object));
}
// Read the 'generated' property
@@ -100,7 +100,7 @@
// Read the 'generator' property
final generator = root['generator'];
- if (generator != null && generator is! String) {
+ if (generator is! String?) {
throw FormatException(
'"generator" in package_config.json must be a string, if given',
);
@@ -124,7 +124,7 @@
}
return PackageConfig(
- configVersion: configVersion as int,
+ configVersion: configVersion,
packages: packages,
generated: generated,
generator: generator,
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index 48c4258..06bba9e 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -24,6 +24,7 @@
import 'command/uploader.dart';
import 'log.dart' as log;
import 'log.dart';
+import 'utils.dart';
/// The information needed for the embedded pub command to send analytics.
@sealed
@@ -56,7 +57,7 @@
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-global';
@override
- String get directory => argResults['directory'];
+ String get directory => argResults.option('directory');
@override
final PubAnalytics? analytics;
@@ -120,6 +121,6 @@
bool get trace => _isVerbose;
bool get _isVerbose {
- return argResults['verbose'] || isVerbose();
+ return argResults.flag('verbose') || isVerbose();
}
}
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index c27fdb7..1b1e3b8 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -102,10 +102,11 @@
final pubspecOverridesFields = _overridesFileFields;
if (pubspecOverridesFields != null) {
pubspecOverridesFields.nodes.forEach((key, _) {
- if (!const {'dependency_overrides'}.contains(key.value)) {
+ final keyNode = key as YamlNode;
+ if (!const {'dependency_overrides'}.contains(keyNode.value)) {
throw SourceSpanApplicationException(
'pubspec_overrides.yaml only supports the `dependency_overrides` field.',
- key.span,
+ keyNode.span,
);
}
});
@@ -175,6 +176,7 @@
if (yaml is YamlMap) {
yaml.nodes.forEach((nameNode, constraintNode) {
+ if (nameNode is! YamlNode) throw AssertionError('Bad state');
final name = nameNode.value;
if (name is! String) {
_error('SDK names must be strings.', nameNode.span);
@@ -254,13 +256,13 @@
this.dependencyOverridesFromOverridesFile = false,
}) : _dependencies = dependencies == null
? null
- : Map.fromIterable(dependencies, key: (range) => range.name),
+ : {for (final d in dependencies) d.name: d},
_devDependencies = devDependencies == null
? null
- : Map.fromIterable(devDependencies, key: (range) => range.name),
+ : {for (final d in devDependencies) d.name: d},
_dependencyOverrides = dependencyOverrides == null
? null
- : Map.fromIterable(dependencyOverrides, key: (range) => range.name),
+ : {for (final d in dependencyOverrides) d.name: d},
_givenSdkConstraints = sdkConstraints ??
UnmodifiableMapView({'dart': SdkConstraint(VersionConstraint.any)}),
_includeDefaultSdkConstraint = false,
@@ -426,61 +428,63 @@
_error('"$field" field must be a map.', node.span);
}
- var nonStringNode =
- node.nodes.keys.firstWhere((e) => e.value is! String, orElse: () => null);
+ var nonStringNode = node.nodes.keys
+ .firstWhereOrNull((e) => e is YamlScalar && e.value is! String);
if (nonStringNode != null) {
- _error('A dependency name must be a string.', nonStringNode.span);
+ _error(
+ 'A dependency name must be a string.',
+ (nonStringNode as YamlNode).span,
+ );
}
node.nodes.forEach(
(nameNode, specNode) {
- var name = nameNode.value;
+ var name = (nameNode as YamlNode).value;
+ if (name is! String) {
+ _error('A dependency name must be a string.', nameNode.span);
+ }
var spec = specNode.value;
if (packageName != null && name == packageName) {
_error('A package may not list itself as a dependency.', nameNode.span);
}
- YamlNode? descriptionNode;
- String? sourceName;
-
+ final String? sourceName;
VersionConstraint versionConstraint = VersionRange();
+ YamlNode? descriptionNode;
if (spec == null) {
sourceName = null;
} else if (spec is String) {
sourceName = null;
versionConstraint =
_parseVersionConstraint(specNode, packageName, fileType);
- } else if (spec is Map) {
+ } else if (specNode is YamlMap) {
// Don't write to the immutable YAML map.
- spec = Map.from(spec);
- var specMap = specNode as YamlMap;
-
- if (spec.containsKey('version')) {
- spec.remove('version');
- versionConstraint = _parseVersionConstraint(
- specMap.nodes['version'],
- packageName,
- fileType,
- );
- }
-
- var sourceNames = spec.keys.toList();
- if (sourceNames.length > 1) {
+ final versionNode = specNode.nodes['version'];
+ versionConstraint = _parseVersionConstraint(
+ versionNode,
+ packageName,
+ fileType,
+ );
+ final otherEntries = specNode.nodes.entries
+ .where((entry) => entry.key.value != 'version')
+ .toList();
+ if (otherEntries.length > 1) {
_error('A dependency may only have one source.', specNode.span);
- } else if (sourceNames.isEmpty) {
+ } else if (otherEntries.isEmpty) {
// Default to a hosted dependency if no source is specified.
sourceName = 'hosted';
+ } else {
+ switch (otherEntries.single) {
+ case MapEntry(key: YamlScalar(value: String s), value: final d):
+ sourceName = s;
+ descriptionNode = d;
+ case MapEntry(key: final k, value: _):
+ _error(
+ 'A source name must be a string.',
+ (k as YamlNode).span,
+ );
+ }
}
-
- sourceName ??= sourceNames.single;
- if (sourceName is! String) {
- _error(
- 'A source name must be a string.',
- specMap.nodes.keys.single.span,
- );
- }
-
- descriptionNode ??= specMap.nodes[sourceName];
} else {
_error(
'A dependency specification must be a string or a mapping.',
@@ -536,7 +540,8 @@
if (node?.value == null) {
return VersionConstraint.any;
}
- if (node!.value is! String) {
+ final value = node!.value;
+ if (value is! String) {
_error('A version constraint must be a string.', node.span);
}
@@ -544,7 +549,7 @@
'version constraint',
node.span,
() {
- var constraint = VersionConstraint.parse(node.value);
+ var constraint = VersionConstraint.parse(value);
return constraint;
},
packageName,
diff --git a/lib/src/pubspec_parse.dart b/lib/src/pubspec_parse.dart
index df9fd3a..d4d6acb 100644
--- a/lib/src/pubspec_parse.dart
+++ b/lib/src/pubspec_parse.dart
@@ -131,7 +131,7 @@
}
_parsedPublishTo = true;
- _publishTo = publishTo;
+ _publishTo = publishTo as String?;
return _publishTo;
}
@@ -161,7 +161,7 @@
if (value is! String) {
falseSecretsError(node.span);
}
- falseSecrets.add(value);
+ falseSecrets.add(value as String);
}
} else {
falseSecretsError(falseSecretsNode.span);
@@ -198,13 +198,17 @@
);
}
- yaml.nodes.forEach((key, value) {
- if (key.value is! String) {
+ var yamlMap = yaml;
+
+ yamlMap.nodes.forEach((key, value) {
+ key = key as YamlNode;
+ final keyValue = key.value;
+ if (keyValue is! String) {
_error('"executables" keys must be strings.', key.span);
}
final keyPattern = RegExp(r'^[a-zA-Z0-9_-]+$');
- if (!keyPattern.hasMatch(key.value)) {
+ if (!keyPattern.hasMatch(keyValue)) {
_error(
'"executables" keys may only contain letters, '
'numbers, hyphens and underscores.',
@@ -212,21 +216,16 @@
);
}
- if (value.value == null) {
- value = key;
- } else if (value.value is! String) {
- _error('"executables" values must be strings or null.', value.span);
- }
-
final valuePattern = RegExp(r'[/\\]');
- if (valuePattern.hasMatch(value.value)) {
- _error(
- '"executables" values may not contain path separators.',
- value.span,
- );
- }
-
- _executables![key.value] = value.value;
+ _executables![keyValue] = switch (value.value) {
+ null => keyValue,
+ String s when valuePattern.hasMatch(s) => _error(
+ '"executables" values may not contain path separators.',
+ value.span,
+ ),
+ String s => s,
+ _ => _error('"executables" values must be strings or null.', value.span)
+ };
});
return _executables!;
@@ -267,7 +266,7 @@
}
/// Throws a [SourceSpanApplicationException] with the given message.
- void _error(String message, SourceSpan? span) {
+ Never _error(String message, SourceSpan? span) {
throw SourceSpanApplicationException(message, span);
}
}
diff --git a/lib/src/solver/package_lister.dart b/lib/src/solver/package_lister.dart
index ce794b7..45ec5b8 100644
--- a/lib/src/solver/package_lister.dart
+++ b/lib/src/solver/package_lister.dart
@@ -275,7 +275,8 @@
var index = lowerBound(
versions,
id,
- compare: (dynamic id1, dynamic id2) => id1.version.compareTo(id2.version),
+ compare: (PackageId id1, PackageId id2) =>
+ id1.version.compareTo(id2.version),
);
assert(index < versions.length);
assert(versions[index].version == id.version);
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index 36401d6..32ef867 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -95,7 +95,7 @@
}
var ref = description['ref'];
- if (ref != null && ref is! String) {
+ if (ref is! String?) {
throw FormatException("The 'ref' field of the description must be a "
'string.');
}
@@ -107,13 +107,17 @@
}
final url = description['url'];
+ if (url is! String) {
+ throw FormatException("The 'url' field of the description "
+ 'must be a string.');
+ }
return PackageId(
name,
version,
GitResolvedDescription(
GitDescription(
url: url,
- ref: ref ?? 'HEAD',
+ ref: ref,
path: _validatedPath(
description['path'],
),
@@ -465,7 +469,7 @@
} on git.GitException catch (error, stackTrace) {
log.error('Failed to reset ${log.bold(package.name)} '
'${package.version}. Error:\n$error');
- log.fine(stackTrace);
+ log.fine(stackTrace.toString());
result.add(
RepairResult(package.name, package.version, this, success: false),
);
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 1b28401..2d7376a 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -279,7 +279,7 @@
version,
ResolvedHostedDescription(
HostedDescription(name, url),
- sha256: _parseContentHash(sha256),
+ sha256: _parseContentHash(sha256 as String?),
),
);
}
@@ -362,7 +362,7 @@
}
final url = u ?? defaultUrl;
- return HostedDescription(name, url);
+ return HostedDescription(name, url as String);
}
static final RegExp _looksLikePackageName =
@@ -407,17 +407,29 @@
if (archiveUrl is! String) {
throw FormatException('archive_url must be a String');
}
+ final isDiscontinued = body['isDiscontinued'] ?? false;
+ if (isDiscontinued is! bool) {
+ throw FormatException('isDiscontinued must be a bool');
+ }
+ final replacedBy = body['replacedBy'];
+ if (replacedBy is! String?) {
+ throw FormatException('replacedBy must be a String');
+ }
+ final retracted = map['retracted'] ?? false;
+ if (retracted is! bool) {
+ throw FormatException('retracted must be a bool');
+ }
final status = PackageStatus(
- isDiscontinued: body['isDiscontinued'] ?? false,
- discontinuedReplacedBy: body['replacedBy'],
- isRetracted: map['retracted'] ?? false,
+ isDiscontinued: isDiscontinued,
+ discontinuedReplacedBy: replacedBy,
+ isRetracted: retracted,
);
return _VersionInfo(
pubspec.version,
pubspec,
Uri.parse(archiveUrl),
status,
- _parseContentHash(archiveSha256),
+ _parseContentHash(archiveSha256 as String?),
);
}).toList();
}
@@ -458,7 +470,12 @@
throw FormatException('version listing must be a mapping');
}
body = decoded;
- result = _versionInfoFromPackageListing(body, ref, url, cache);
+ result = _versionInfoFromPackageListing(
+ body as Map<String, dynamic>,
+ ref,
+ url,
+ cache,
+ );
} on Exception catch (error, stackTrace) {
_throwFriendlyError(error, stackTrace, packageName, hostedUrl);
}
@@ -982,7 +999,7 @@
'${package.version}';
if (url != defaultUrl) message += ' from $url';
log.error('$message. Error:\n$error');
- log.fine(stackTrace);
+ log.fine(stackTrace.toString());
tryDeleteEntry(package.dir);
return RepairResult(
diff --git a/lib/src/source/path.dart b/lib/src/source/path.dart
index 83358ea..8db723e 100644
--- a/lib/src/source/path.dart
+++ b/lib/src/source/path.dart
@@ -117,7 +117,7 @@
}
path = p.normalize(
- p.absolute(p.join(containingDir, description['path'])),
+ p.absolute(p.join(containingDir, path)),
);
}
diff --git a/lib/src/system_cache.dart b/lib/src/system_cache.dart
index 971adba..ff2b535 100644
--- a/lib/src/system_cache.dart
+++ b/lib/src/system_cache.dart
@@ -67,8 +67,10 @@
})();
/// The available sources.
- late final _sources =
- Map.fromIterable([hosted, git, path, sdk], key: (source) => source.name);
+ late final _sources = Map<String, Source>.fromIterable(
+ [hosted, git, path, sdk],
+ key: (source) => (source as Source).name,
+ );
Source sources(String? name) {
return name == null
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 061bd7c..4f144e4 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -9,6 +9,7 @@
import 'dart:math' as math;
import 'dart:typed_data';
+import 'package:args/args.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:pub_semver/pub_semver.dart';
@@ -110,7 +111,9 @@
}) {
var completer = Completer<T>();
void wrappedCallback() {
- Future.sync(callback).then(completer.complete).catchError((e, stackTrace) {
+ Future.sync(callback)
+ .then(completer.complete)
+ .catchError((Object e, StackTrace? stackTrace) {
// [stackTrace] can be null if we're running without [captureStackChains],
// since dart:io will often throw errors without stack traces.
if (stackTrace != null) {
@@ -118,7 +121,9 @@
} else {
stackTrace = Chain([]);
}
- if (!completer.isCompleted) completer.completeError(e, stackTrace);
+ if (!completer.isCompleted) {
+ completer.completeError(e, stackTrace);
+ }
});
}
@@ -147,12 +152,13 @@
Future<List<T>> waitAndPrintErrors<T>(Iterable<Future<T>> futures) {
return Future.wait(
futures.map((future) {
- return future.catchError((error, stackTrace) {
+ return future.catchError((Object error, StackTrace? stackTrace) {
log.exception(error, stackTrace);
+ // ignore: only_throw_errors
throw error;
});
}),
- ).catchError((error, stackTrace) {
+ ).catchError((Object error, StackTrace? stackTrace) {
throw SilentException(error, stackTrace);
});
}
@@ -287,7 +293,7 @@
) async {
int? minIndex;
T? minOrderBy;
- List valuesList = values.toList();
+ var valuesList = values.toList();
final orderByResults = await Future.wait(values.map(orderBy));
for (var i = 0; i < orderByResults.length; i++) {
final elementOrderBy = orderByResults[i];
@@ -735,3 +741,10 @@
await Future.delayed(delay < maxDelay ? delay : maxDelay);
}
}
+
+extension RetrieveFlags on ArgResults {
+ bool flag(String name) => this[name] as bool;
+
+ String option(String name) => this[name] as String;
+ String? optionWithoutDefault(String name) => this[name] as String?;
+}
diff --git a/lib/src/validator/pubspec_typo.dart b/lib/src/validator/pubspec_typo.dart
index c51c678..0c2ac9a 100644
--- a/lib/src/validator/pubspec_typo.dart
+++ b/lib/src/validator/pubspec_typo.dart
@@ -19,6 +19,7 @@
if (_validPubspecKeys.contains(key)) {
continue;
}
+ if (key is! String) continue;
var bestLevenshteinRatio = 100.0;
var closestKey = '';
diff --git a/lib/src/validator/strict_dependencies.dart b/lib/src/validator/strict_dependencies.dart
index 728f592..50fd208 100644
--- a/lib/src/validator/strict_dependencies.dart
+++ b/lib/src/validator/strict_dependencies.dart
@@ -35,7 +35,7 @@
} on AnalyzerErrorGroup catch (e, s) {
// Ignore files that do not parse.
log.fine(getErrorMessage(e));
- log.fine(Chain.forTrace(s).terse);
+ log.fine(Chain.forTrace(s).terse.toString());
continue;
}
diff --git a/test/cache/list_test.dart b/test/cache/list_test.dart
index c5fd2fb..72f9339 100644
--- a/test/cache/list_test.dart
+++ b/test/cache/list_test.dart
@@ -9,7 +9,7 @@
import '../test_pub.dart';
void main() {
- String hostedDir(package) {
+ String hostedDir(String package) {
return path.join(d.sandbox, cachePath, 'hosted', 'pub.dev', package);
}
diff --git a/test/dependency_services/dependency_services_test.dart b/test/dependency_services/dependency_services_test.dart
index 412be30..4dbef36 100644
--- a/test/dependency_services/dependency_services_test.dart
+++ b/test/dependency_services/dependency_services_test.dart
@@ -10,6 +10,7 @@
import 'package:pub_semver/pub_semver.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
+import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';
import '../descriptor.dart' as d;
@@ -102,7 +103,7 @@
await context.runDependencyServices(['list']);
final report = await context.runDependencyServices(['report']);
if (reportAssertions != null) {
- reportAssertions(json.decode(report));
+ reportAssertions(json.decode(report) as Map);
}
final input = json.encode({
'dependencyChanges': upgrades,
@@ -120,7 +121,7 @@
'--snapshot=$snapshot',
p.join('bin', 'dependency_services.dart'),
]);
- expect(r.exitCode, 0, reason: r.stderr);
+ expect(r.exitCode, 0, reason: r.stderr as String);
});
tearDownAll(() {
@@ -254,7 +255,7 @@
final lockFileYaml = YamlEditor(
lockFile.readAsStringSync(),
);
- for (final p in lockFileYaml.parseAt(['packages']).value.entries) {
+ for (final p in (lockFileYaml.parseAt(['packages']) as YamlMap).entries) {
lockFileYaml.remove(['packages', p.key, 'description', 'sha256']);
}
lockFile.writeAsStringSync(lockFileYaml.toString());
@@ -289,7 +290,8 @@
final lockFileYaml = YamlEditor(
lockFile.readAsStringSync(),
);
- for (final p in lockFileYaml.parseAt(['packages']).value.entries) {
+ for (final p
+ in lockFileYaml.parseAt(['packages']).value.entries as Iterable) {
lockFileYaml.update(
['packages', p.key, 'description', 'url'],
'https://pub.dartlang.org',
diff --git a/test/descriptor.dart b/test/descriptor.dart
index d41001e..38f9161 100644
--- a/test/descriptor.dart
+++ b/test/descriptor.dart
@@ -175,14 +175,18 @@
/// validated since they will often lack the dependencies section that the
/// real pubspec being compared against has. You usually only need to pass
/// `true` for this if you plan to call [create] on the resulting descriptor.
-Descriptor cacheDir(Map packages, {int? port, bool includePubspecs = false}) {
+Descriptor cacheDir(
+ Map<String, dynamic> packages, {
+ int? port,
+ bool includePubspecs = false,
+}) {
var contents = <Descriptor>[];
packages.forEach((name, versions) {
if (versions is! List) versions = [versions];
for (var version in versions) {
var packageContents = [libDir(name, '$name $version')];
if (includePubspecs) {
- packageContents.add(libPubspec(name, version));
+ packageContents.add(libPubspec(name, version as String));
}
contents.add(dir('$name-$version', packageContents));
}
diff --git a/test/descriptor/package_config.dart b/test/descriptor/package_config.dart
index b508dc6..2b644c2 100644
--- a/test/descriptor/package_config.dart
+++ b/test/descriptor/package_config.dart
@@ -52,9 +52,7 @@
fail("File not found: '$packageConfigFile'.");
}
- Map<String, dynamic> rawJson = json.decode(
- await File(packageConfigFile).readAsString(),
- );
+ final rawJson = json.decode(await File(packageConfigFile).readAsString());
PackageConfig config;
try {
config = PackageConfig.fromJson(rawJson);
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart
index cf504d6..6ab32ad 100644
--- a/test/embedding/embedding_test.dart
+++ b/test/embedding/embedding_test.dart
@@ -92,7 +92,7 @@
Platform.resolvedExecutable,
['--snapshot=$snapshot', _commandRunner],
);
- expect(r.exitCode, 0, reason: r.stderr);
+ expect(r.exitCode, 0, reason: r.stderr as String);
});
tearDownAll(() {
diff --git a/test/embedding/get_executable_for_command_test.dart b/test/embedding/get_executable_for_command_test.dart
index 8781897..f56c57c 100644
--- a/test/embedding/get_executable_for_command_test.dart
+++ b/test/embedding/get_executable_for_command_test.dart
@@ -17,7 +17,7 @@
Future<void> testGetExecutable(
String command,
String root, {
- allowSnapshot = true,
+ bool allowSnapshot = true,
executable,
packageConfig,
errorMessage,
diff --git a/test/lish/many_files_test.dart b/test/lish/many_files_test.dart
index 50a45f9..dd54737 100644
--- a/test/lish/many_files_test.dart
+++ b/test/lish/many_files_test.dart
@@ -79,7 +79,7 @@
'${result.stderr}');
}
- argMax = int.parse(result.stdout);
+ argMax = int.parse(result.stdout as String);
}
var appRoot = p.join(d.sandbox, appPath);
diff --git a/test/package_server.dart b/test/package_server.dart
index a2dd4f5..b5d07ba 100644
--- a/test/package_server.dart
+++ b/test/package_server.dart
@@ -342,7 +342,7 @@
// Overrides the calculated sha256.
String? sha256;
- Version get version => Version.parse(pubspec['version']);
+ Version get version => Version.parse(pubspec['version'] as String);
_ServedPackageVersion(this.pubspec, {required this.contents, this.headers});
diff --git a/test/rate_limited_scheduler_test.dart b/test/rate_limited_scheduler_test.dart
index 6c94751..3a387c3 100644
--- a/test/rate_limited_scheduler_test.dart
+++ b/test/rate_limited_scheduler_test.dart
@@ -181,7 +181,7 @@
Future<String?> f(String i) async {
isBeingProcessed[i]!.complete();
await completers[i]!.future;
- return Zone.current['zoneValue'];
+ return Zone.current['zoneValue'] as String?;
}
final scheduler = RateLimitedScheduler(f, maxConcurrentOperations: 2);
diff --git a/test/test_pub.dart b/test/test_pub.dart
index 8f84125..f79ac4b 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -149,7 +149,7 @@
int? exitCode,
Map<String, String?>? environment,
String? workingDirectory,
- includeParentHomeAndPath = true,
+ bool includeParentHomeAndPath = true,
}) async {
if (error != null && warning != null) {
throw ArgumentError("Cannot pass both 'error' and 'warning'.");
@@ -348,7 +348,7 @@
String? workingDirectory,
Map<String, String?>? environment,
List<String>? input,
- includeParentHomeAndPath = true,
+ bool includeParentHomeAndPath = true,
}) async {
exitCode ??= exit_codes.SUCCESS;
// Cannot pass both output and outputJson.
@@ -486,7 +486,7 @@
String? workingDirectory,
Map<String, String?>? environment,
bool verbose = true,
- includeParentHomeAndPath = true,
+ bool includeParentHomeAndPath = true,
}) async {
args ??= [];
@@ -596,8 +596,8 @@
/// This is protected.
PubProcess(
- process,
- description, {
+ Process process,
+ String description, {
Encoding encoding = utf8,
bool forwardStdio = false,
}) : super(
@@ -710,7 +710,7 @@
Iterable<String>? sandbox,
Map<String, String>? hosted,
}) {
- var dependencies = {};
+ var dependencies = <String, dynamic>{};
if (sandbox != null) {
for (var package in sandbox) {
@@ -866,15 +866,15 @@
void _validateOutputJson(
List<String> failures,
String pipe,
- expected,
+ Object? expected,
String actualText,
) {
late Map actual;
try {
- actual = jsonDecode(actualText);
+ actual = jsonDecode(actualText) as Map;
} on FormatException {
failures.add('Expected $pipe JSON:');
- failures.add(expected);
+ failures.add(expected.toString());
failures.add('Got invalid JSON:');
failures.add(actualText);
}
@@ -884,7 +884,7 @@
actual['log']?.removeWhere(
(entry) =>
entry['level'] == 'Fine' &&
- entry['message'].startsWith('Not yet complete after'),
+ (entry['message'] as String).startsWith('Not yet complete after'),
);
// Match against the expectation.
diff --git a/test/utils_test.dart b/test/utils_test.dart
index 9d71e31..62d5576 100644
--- a/test/utils_test.dart
+++ b/test/utils_test.dart
@@ -142,8 +142,9 @@
group('minByAsync', () {
test('is stable', () async {
{
- final completers = <String, Completer>{};
- Completer completer(k) => completers.putIfAbsent(k, Completer.new);
+ final completers = <String, Completer<String>>{};
+ Completer<String> completer(String k) =>
+ completers.putIfAbsent(k, Completer.new);
Future<int> lengthWhenComplete(String s) async {
await completer(s).future;
return s.length;
@@ -153,15 +154,16 @@
minByAsync(['aa', 'a', 'b', 'ccc'], lengthWhenComplete),
completion('a'),
);
- completer('aa').complete();
- completer('b').complete();
- completer('a').complete();
- completer('ccc').complete();
+ completer('aa').complete('');
+ completer('b').complete('');
+ completer('a').complete('');
+ completer('ccc').complete('');
await w;
}
{
- final completers = <String, Completer>{};
- Completer completer(k) => completers.putIfAbsent(k, Completer.new);
+ final completers = <String, Completer<String>>{};
+ Completer<String> completer(String k) =>
+ completers.putIfAbsent(k, Completer.new);
Future<int> lengthWhenComplete(String s) async {
await completer(s).future;
return s.length;
@@ -171,10 +173,10 @@
minByAsync(['aa', 'a', 'b', 'ccc'], lengthWhenComplete),
completion('a'),
);
- completer('ccc').complete();
- completer('a').complete();
- completer('b').complete();
- completer('aa').complete();
+ completer('ccc').complete('');
+ completer('a').complete('');
+ completer('b').complete('');
+ completer('aa').complete('');
await w;
}
});
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index df3ae2b..c5b89a5 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -1985,10 +1985,10 @@
LockFile.load(p.join(d.sandbox, appPath, 'pubspec.lock'), registry);
var resultPubspec = Pubspec.fromMap({'dependencies': result}, registry);
- var ids = Map.from(lockFile.packages);
+ var ids = {...lockFile.packages};
for (var dep in resultPubspec.dependencies.values) {
expect(ids, contains(dep.name));
- var id = ids.remove(dep.name);
+ var id = ids.remove(dep.name)!;
final description = dep.description;
if (description is HostedDescription &&
(description.url == SystemCache().hosted.defaultUrl)) {
diff --git a/tool/extract_all_pub_dev.dart b/tool/extract_all_pub_dev.dart
index 5d69ab3..9301723 100644
--- a/tool/extract_all_pub_dev.dart
+++ b/tool/extract_all_pub_dev.dart
@@ -24,7 +24,7 @@
request.attachMetadataHeaders();
final response = await globalHttpClient.fetch(request);
final result = json.decode(response.body);
- return List<String>.from(result['packages']);
+ return List<String>.from(result['packages'] as List);
}
Future<List<String>> versionArchiveUrls(String packageName) async {
@@ -33,7 +33,9 @@
request.attachMetadataHeaders();
final response = await globalHttpClient.fetch(request);
final result = json.decode(response.body);
- return List<String>.from(result['versions'].map((v) => v['archive_url']));
+ return (result['versions'] as List)
+ .map((v) => v['archive_url'] as String)
+ .toList();
}
Future<void> main() async {
@@ -41,11 +43,11 @@
var failures = <Map<String, dynamic>?>[];
if (fileExists(statusFilename)) {
final json = jsonDecode(readTextFile(statusFilename));
- for (final packageName in json['packages'] ?? []) {
- alreadyDonePackages.add(packageName);
+ for (final packageName in json['packages'] as Iterable? ?? []) {
+ alreadyDonePackages.add(packageName as String);
}
- for (final failure in json['failures'] ?? []) {
- failures.add(failure);
+ for (final failure in (json['failures'] ?? []) as Iterable) {
+ failures.add(failure as Map<String, dynamic>);
}
}
log.message('Already processed ${alreadyDonePackages.length} packages');
diff --git a/tool/test-bin/pub_command_runner.dart b/tool/test-bin/pub_command_runner.dart
index 9192079..36094d8 100644
--- a/tool/test-bin/pub_command_runner.dart
+++ b/tool/test-bin/pub_command_runner.dart
@@ -12,6 +12,7 @@
import 'package:pub/src/command.dart';
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/log.dart' as log;
+import 'package:pub/src/utils.dart';
import 'package:usage/usage.dart';
final Analytics loggingAnalytics = _LoggingAnalytics();
@@ -77,7 +78,7 @@
}
class Runner extends CommandRunner<int> {
- late ArgResults _options;
+ late ArgResults _results;
Runner() : super('pub_command_runner', 'Tests the embeddable pub command.') {
final analytics = Platform.environment['_PUB_LOG_ANALYTICS'] == 'true'
@@ -87,7 +88,10 @@
)
: null;
addCommand(
- pubCommand(analytics: analytics, isVerbose: () => _options['verbose'])
+ pubCommand(
+ analytics: analytics,
+ isVerbose: () => _results.flag('verbose'),
+ )
..addSubcommand(ThrowingCommand())
..addSubcommand(EnsurePubspecResolvedCommand()),
);
@@ -98,11 +102,11 @@
@override
Future<int> run(Iterable<String> args) async {
try {
- _options = super.parse(args);
- if (_options['verbose']) {
+ _results = super.parse(args);
+ if (_results.flag('verbose')) {
log.verbosity = log.Verbosity.all;
}
- return await runCommand(_options);
+ return await runCommand(_results);
} on UsageException catch (error) {
log.exception(error);
return exit_codes.USAGE;