diff --git a/analysis_options.yaml b/analysis_options.yaml index 2af0e96ef0..fc8e2448f1 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -52,6 +52,7 @@ linter: - prefer_conditional_assignment - prefer_contains - prefer_final_fields + - prefer_final_in_for_each - prefer_final_locals - prefer_for_elements_to_map_fromIterable - prefer_generic_function_type_aliases diff --git a/app/lib/account/backend.dart b/app/lib/account/backend.dart index f4a417b47e..7884d17cff 100644 --- a/app/lib/account/backend.dart +++ b/app/lib/account/backend.dart @@ -241,7 +241,7 @@ class AccountBackend { /// Uses in-memory cache to store entries locally for up to 10 minutes. Future> getEmailsOfUserIds(List userIds) async { final result = []; - for (String userId in userIds) { + for (final userId in userIds) { result.add(await getEmailOfUserId(userId)); } return result; diff --git a/app/lib/account/consent_backend.dart b/app/lib/account/consent_backend.dart index 51d7ea630b..c8c8b8bea0 100644 --- a/app/lib/account/consent_backend.dart +++ b/app/lib/account/consent_backend.dart @@ -231,7 +231,7 @@ class ConsentBackend { Future deleteObsoleteConsents() async { final query = _db.query() ..filter('expires <', clock.now().toUtc()); - await for (var entry in query.run()) { + await for (final entry in query.run()) { try { await _delete(entry, (a) => a.onExpire(entry)); } catch (e) { diff --git a/app/lib/admin/tools/delete_all_staging.dart b/app/lib/admin/tools/delete_all_staging.dart index 8f6b37c533..7acc609d9a 100644 --- a/app/lib/admin/tools/delete_all_staging.dart +++ b/app/lib/admin/tools/delete_all_staging.dart @@ -92,7 +92,7 @@ Future _batchedQuery( budget = _defaultBudget; } - await for (Model m in query.run()) { + await for (final m in query.run()) { final size = _estimateSize(m); if (size * 4 >= _defaultBudget) { flush(); diff --git a/app/lib/frontend/static_files.dart b/app/lib/frontend/static_files.dart index c253742edc..7a15299799 100644 --- a/app/lib/frontend/static_files.dart +++ b/app/lib/frontend/static_files.dart @@ -122,7 +122,7 @@ class StaticFileCache { '/static/css/style.css', '/static/js/script.dart.js', }; - for (String path in paths) { + for (final path in paths) { final file = StaticFile(path, 'text/mock', [], clock.now(), 'mocked_hash_${path.hashCode.abs()}'); cache.addFile(file); @@ -279,7 +279,7 @@ class StaticUrls { Future _detectLastModified(Directory dir) async { DateTime? lastModified; - await for (FileSystemEntity fse in dir.list(recursive: true)) { + await for (final fse in dir.list(recursive: true)) { if (fse is File) { final lm = await fse.lastModified(); if (lastModified == null || lastModified.isBefore(lm)) { diff --git a/app/lib/frontend/templates/detail_page.dart b/app/lib/frontend/templates/detail_page.dart index 69108a7dac..c511aacf93 100644 --- a/app/lib/frontend/templates/detail_page.dart +++ b/app/lib/frontend/templates/detail_page.dart @@ -45,7 +45,7 @@ d.Node renderDetailPage({ d.Node? footerNode, }) { // active: the first one with content - for (Tab tab in tabs) { + for (final tab in tabs) { if (tab.contentNode != null) { tab.isActive = true; break; diff --git a/app/lib/frontend/templates/views/pkg/info_box.dart b/app/lib/frontend/templates/views/pkg/info_box.dart index 1b2bb39d40..c6a651a0c5 100644 --- a/app/lib/frontend/templates/views/pkg/info_box.dart +++ b/app/lib/frontend/templates/views/pkg/info_box.dart @@ -61,10 +61,10 @@ d.Node packageInfoBoxNode({ if (screenshots != null && screenshots.isNotEmpty) { thumbnailUrl = imageStorage.getImageUrl( package.name!, version.version!, screenshots.first.webp190Thumbnail); - for (ProcessedScreenshot s in screenshots) { + for (final screenshot in screenshots) { screenshotUrls.add(imageStorage.getImageUrl( - package.name!, version.version!, s.webpImage)); - screenshotDescriptions.add(s.description); + package.name!, version.version!, screenshot.webpImage)); + screenshotDescriptions.add(screenshot.description); } } return d.fragment([ diff --git a/app/lib/frontend/templates/views/pkg/package_list.dart b/app/lib/frontend/templates/views/pkg/package_list.dart index 358afb4083..31aca6d73a 100644 --- a/app/lib/frontend/templates/views/pkg/package_list.dart +++ b/app/lib/frontend/templates/views/pkg/package_list.dart @@ -6,7 +6,6 @@ import 'package:_pub_shared/format/x_ago_format.dart'; import 'package:_pub_shared/search/search_form.dart'; import 'package:_pub_shared/search/tags.dart'; import 'package:clock/clock.dart'; -import 'package:pana/pana.dart'; import '../../../../package/models.dart'; import '../../../../package/screenshots/backend.dart'; @@ -148,10 +147,10 @@ d.Node _packageItem( thumbnailUrl = imageStorage.getImageUrl( view.name, releases.stable.version, screenshots.first.webp100Thumbnail); - for (ProcessedScreenshot s in screenshots) { + for (final screenshot in screenshots) { screenshotUrls.add(imageStorage.getImageUrl( - view.name, releases.stable.version, s.webpImage)); - screenshotDescriptions.add(s.description); + view.name, releases.stable.version, screenshot.webpImage)); + screenshotDescriptions.add(screenshot.description); } } diff --git a/app/lib/search/mem_index.dart b/app/lib/search/mem_index.dart index 5ccf43a11f..69519c037b 100644 --- a/app/lib/search/mem_index.dart +++ b/app/lib/search/mem_index.dart @@ -75,7 +75,7 @@ class InMemoryPackageIndex { _descrIndex.add(doc.package, doc.description); _readmeIndex.add(doc.package, doc.readme); - for (ApiDocPage page in doc.apiDocPages ?? const []) { + for (final ApiDocPage page in doc.apiDocPages ?? const []) { final pageId = _apiDocPageId(doc.package, page); if (page.symbols != null && page.symbols!.isNotEmpty) { _apiSymbolIndex.add(pageId, page.symbols!.join(' ')); @@ -108,10 +108,10 @@ class InMemoryPackageIndex { packages.removeWhere((package) { final doc = _packages[package]!; if (doc.dependencies.isEmpty) return true; - for (String dependency in query.parsedQuery.allDependencies) { + for (final dependency in query.parsedQuery.allDependencies) { if (!doc.dependencies.containsKey(dependency)) return true; } - for (String dependency in query.parsedQuery.refDependencies) { + for (final dependency in query.parsedQuery.refDependencies) { final type = doc.dependencies[dependency]; if (type == null || type == DependencyTypes.transitive) return true; } @@ -315,7 +315,7 @@ class InMemoryPackageIndex { final phrases = extractExactPhrases(text); if (!aborted && phrases.isNotEmpty) { final matched = {}; - for (String package in score.getKeys()) { + for (final package in score.getKeys()) { final doc = _packages[package]!; final bool matchedAllPhrases = phrases.every((phrase) => doc.package.contains(phrase) || diff --git a/app/lib/search/text_utils.dart b/app/lib/search/text_utils.dart index edad10c28b..db1324da59 100644 --- a/app/lib/search/text_utils.dart +++ b/app/lib/search/text_utils.dart @@ -95,7 +95,7 @@ Map? tokenize(String? originalText, {bool isSplit = false}) { final tokens = {}; final words = isSplit ? [originalText] : splitForIndexing(originalText); - for (String word in words) { + for (final word in words) { if (word.length > _maxWordLength) { continue; } diff --git a/app/lib/search/token_index.dart b/app/lib/search/token_index.dart index 1d55992765..4077377240 100644 --- a/app/lib/search/token_index.dart +++ b/app/lib/search/token_index.dart @@ -172,7 +172,7 @@ class TokenIndex { if (tokens == null || tokens.isEmpty) { return; } - for (String token in tokens.keys) { + for (final token in tokens.keys) { final Map weights = _inverseIds.putIfAbsent(token, () => {}); weights[id] = math.max(weights[id] ?? 0.0, tokens[token]!); @@ -219,8 +219,8 @@ class TokenIndex { Map _scoreDocs(TokenMatch tokenMatch, {double weight = 1.0, int wordCount = 1, Set? limitToIds}) { // Summarize the scores for the documents. - final Map docScores = {}; - for (String token in tokenMatch.tokens) { + final docScores = {}; + for (final token in tokenMatch.tokens) { final docWeights = _inverseIds[token]!; for (final e in docWeights.entries) { if (limitToIds != null && !limitToIds.contains(e.key)) continue; diff --git a/app/lib/shared/datastore.dart b/app/lib/shared/datastore.dart index 64d651ff15..ec21b5097a 100644 --- a/app/lib/shared/datastore.dart +++ b/app/lib/shared/datastore.dart @@ -82,7 +82,7 @@ extension DatastoreDBExt on DatastoreDB { final deletes = []; var found = 0; var deleted = 0; - await for (T model in query.run()) { + await for (final model in query.run()) { found++; if (where == null || await where(model)) { deletes.add(model); diff --git a/app/lib/shared/integrity.dart b/app/lib/shared/integrity.dart index 065999e9f5..05316c8f34 100644 --- a/app/lib/shared/integrity.dart +++ b/app/lib/shared/integrity.dart @@ -448,7 +448,7 @@ class IntegrityChecker { } } - await for (PackageVersionInfo pvi in pviQuery.run()) { + await for (final pvi in pviQuery.run()) { final key = pvi.qualifiedVersionKey; pviKeys.add(key); yield* checkPackageVersionKey('PackageVersionInfo', key); @@ -465,7 +465,7 @@ class IntegrityChecker { referencedAssetIds.add(key.assetId(kind)); } } - for (QualifiedVersionKey key in qualifiedVersionKeys) { + for (final key in qualifiedVersionKeys) { if (!pviKeys.contains(key)) { yield 'PackageVersion "$key" has no PackageVersionInfo.'; } @@ -475,7 +475,7 @@ class IntegrityChecker { final pvaQuery = _db.query() ..filter('package =', p.name); final foundAssetIds = {}; - await for (PackageVersionAsset pva in pvaQuery.run()) { + await for (final pva in pvaQuery.run()) { final key = pva.qualifiedVersionKey; if (pva.id != Uri(pathSegments: [pva.package!, pva.version!, pva.kind!]).path) { diff --git a/app/lib/shared/model_properties.dart b/app/lib/shared/model_properties.dart index e5376c8fd2..9e906e1467 100644 --- a/app/lib/shared/model_properties.dart +++ b/app/lib/shared/model_properties.dart @@ -17,7 +17,7 @@ class CompatibleListProperty extends Property { bool validate(ModelDB db, Object? value) { if (!super.validate(db, value) || value is! List) return false; - for (var entry in value) { + for (final entry in value) { if (!subProperty.validate(db, entry)) return false; } return true; diff --git a/app/lib/shared/storage.dart b/app/lib/shared/storage.dart index 72c8339f66..c534820181 100644 --- a/app/lib/shared/storage.dart +++ b/app/lib/shared/storage.dart @@ -365,7 +365,7 @@ class VersionedJsonStorage { Future deleteOldData({Duration? minAgeThreshold}) async { var found = 0; var deleted = 0; - await for (BucketEntry entry in _bucket.list(prefix: _prefix)) { + await for (final entry in _bucket.list(prefix: _prefix)) { if (entry.isDirectory) { continue; } diff --git a/app/lib/shared/urls.dart b/app/lib/shared/urls.dart index 7da3590449..87273df6f7 100644 --- a/app/lib/shared/urls.dart +++ b/app/lib/shared/urls.dart @@ -390,7 +390,7 @@ String? getRepositoryUrl( String branch = 'master', }) { if (repository == null || repository.isEmpty) return null; - for (var key in _repositoryReplacePrefixes.keys) { + for (final key in _repositoryReplacePrefixes.keys) { if (repository!.startsWith(key)) { repository = repository.replaceFirst(key, _repositoryReplacePrefixes[key]!); diff --git a/app/test/frontend/handlers/_utils.dart b/app/test/frontend/handlers/_utils.dart index e63498992f..7dd76e39d9 100644 --- a/app/test/frontend/handlers/_utils.dart +++ b/app/test/frontend/handlers/_utils.dart @@ -123,13 +123,13 @@ Future expectHtmlResponse( parseAndValidateHtml(content); expect(content, contains('')); expect(content, contains('')); - for (Pattern p in present) { + for (final p in present) { if (p.allMatches(content).isEmpty) { print(content); throw Exception('$p is missing from the content.'); } } - for (Pattern p in absent) { + for (final p in absent) { if (p.allMatches(content).isNotEmpty) { throw Exception('$p is present in the content.'); } diff --git a/app/test/frontend/static_files_test.dart b/app/test/frontend/static_files_test.dart index 016469ec9d..e3fdc0b0d8 100644 --- a/app/test/frontend/static_files_test.dart +++ b/app/test/frontend/static_files_test.dart @@ -100,7 +100,7 @@ void main() { '/static/material/bundle/script.min.js', ]; - for (String file in files) { + for (final file in files) { final f = cache.getFile(file)!; expect(f, isNotNull, reason: file); expect(f.etag.contains('mocked_hash_'), isFalse, reason: file); diff --git a/app/test/search/token_index_test.dart b/app/test/search/token_index_test.dart index 75e14d2f7a..dbd8c1f6b6 100644 --- a/app/test/search/token_index_test.dart +++ b/app/test/search/token_index_test.dart @@ -98,7 +98,7 @@ void main() { 'location_picker', 'background_location_updates', ]; - for (String name in names) { + for (final name in names) { index.add(name, name); } final match = index.search('location'); diff --git a/pkg/_pub_shared/lib/validation/html/html_validation.dart b/pkg/_pub_shared/lib/validation/html/html_validation.dart index 0539d18d6a..a52b0e850d 100644 --- a/pkg/_pub_shared/lib/validation/html/html_validation.dart +++ b/pkg/_pub_shared/lib/validation/html/html_validation.dart @@ -60,7 +60,7 @@ void validateHtml(Node root) { // All links must have rel="noopener" final links = querySelectorAll('a'); - for (Element elem in links) { + for (final elem in links) { if (elem.attributes['target'] == '_blank') { if (!elem.attributes.containsKey('rel')) { throw AssertionError( @@ -117,7 +117,7 @@ void validateHtml(Node root) { // No inline script tag. final scripts = querySelectorAll('script'); - for (Element elem in scripts) { + for (final elem in scripts) { if (elem.attributes['type'] == 'application/ld+json') { if (elem.attributes.length != 1) { throw AssertionError( diff --git a/pkg/_pub_shared/test/search/search_form_test.dart b/pkg/_pub_shared/test/search/search_form_test.dart index e963527b0e..85504c7a38 100644 --- a/pkg/_pub_shared/test/search/search_form_test.dart +++ b/pkg/_pub_shared/test/search/search_form_test.dart @@ -99,7 +99,7 @@ void main() { group('SearchOrder enum', () { test('serialization', () { - for (var value in SearchOrder.values) { + for (final value in SearchOrder.values) { final serialized = value.name; expect(serialized, isNotEmpty); final SearchOrder? deserialized = parseSearchOrder(serialized); diff --git a/pkg/code_coverage/lib/format_lcov.dart b/pkg/code_coverage/lib/format_lcov.dart index 4afca72aed..f737e9a0ab 100644 --- a/pkg/code_coverage/lib/format_lcov.dart +++ b/pkg/code_coverage/lib/format_lcov.dart @@ -14,7 +14,7 @@ Future main() async { .where((f) => f is File) .cast() .toList(); - for (File file in files) { + for (final file in files) { final coverage = await file.readAsString(); if (coverage.isEmpty) { print('${file.path} is empty.'); @@ -35,7 +35,7 @@ Future main() async { } } - for (String path in _lineExecCounts.keys) { + for (final path in _lineExecCounts.keys) { final counts = _lineExecCounts[path]; final total = counts!.length; final covered = counts.values.where((i) => i > 0).length; @@ -66,7 +66,7 @@ Future main() async { ].join(', ')); final keys = _tree.keys.toList()..sort(); - for (String key in keys) { + for (final key in keys) { final entry = _tree[key]; final pctStr = entry!.percentAsString; final sb = StringBuffer(); diff --git a/pkg/code_coverage/lib/generate_all_tests.dart b/pkg/code_coverage/lib/generate_all_tests.dart index 1816f8de4e..70ff897611 100644 --- a/pkg/code_coverage/lib/generate_all_tests.dart +++ b/pkg/code_coverage/lib/generate_all_tests.dart @@ -39,7 +39,7 @@ String _generateTestContent(List files) { final imports = []; final calls = []; - for (String file in files) { + for (final file in files) { final alias = file.substring(0, file.length - 10).replaceAll('/', '_'); imports.add("import '$file' as $alias;"); calls.add(" group('$file', $alias.main);"); diff --git a/pkg/fake_gcloud/lib/mem_datastore.dart b/pkg/fake_gcloud/lib/mem_datastore.dart index e67af2280f..106e1772c2 100644 --- a/pkg/fake_gcloud/lib/mem_datastore.dart +++ b/pkg/fake_gcloud/lib/mem_datastore.dart @@ -243,7 +243,7 @@ class MemDatastore implements Datastore { ).toList(); if (query.orders != null && query.orders!.isNotEmpty) { items.sort((a, b) { - for (Order o in query.orders!) { + for (final o in query.orders!) { if (a.unIndexedProperties.contains(o.propertyName) || b.unIndexedProperties.contains(o.propertyName)) { throw DatastoreError( diff --git a/pkg/fake_gcloud/lib/mem_storage.dart b/pkg/fake_gcloud/lib/mem_storage.dart index 19a34de282..c95903d1b3 100644 --- a/pkg/fake_gcloud/lib/mem_storage.dart +++ b/pkg/fake_gcloud/lib/mem_storage.dart @@ -47,7 +47,7 @@ class MemStorage implements Storage { @override Stream listBucketNames() async* { - for (String name in _buckets.keys) { + for (final name in _buckets.keys) { yield name; } } @@ -261,7 +261,7 @@ class _Bucket implements Bucket { final isDirPrefix = prefix.isEmpty || (delimiter.isNotEmpty && prefix.endsWith(delimiter)); final segments = {}; - for (String name in _files.keys) { + for (final name in _files.keys) { bool matchesPrefix() { // without prefix, return everything if (prefix!.isEmpty) return true; diff --git a/pkg/pub_integration/lib/script/dev_version.dart b/pkg/pub_integration/lib/script/dev_version.dart index f36ce3964d..8486c76bf1 100644 --- a/pkg/pub_integration/lib/script/dev_version.dart +++ b/pkg/pub_integration/lib/script/dev_version.dart @@ -177,12 +177,12 @@ class DevVersionScript { {List? present, List? absent}) { // removing title attributes to keep patterns simple content = content!.replaceAll(RegExp(' title=".*?"'), ''); - for (Pattern p in present ?? []) { + for (final p in present ?? const []) { if (p.allMatches(content).isEmpty) { throw Exception('$p is missing from the content.'); } } - for (Pattern p in absent ?? []) { + for (final p in absent ?? const []) { if (p.allMatches(content).isNotEmpty) { throw Exception('$p is present in the content.'); } diff --git a/pkg/pub_integration/lib/src/test_browser.dart b/pkg/pub_integration/lib/src/test_browser.dart index 04a59e8eca..7484b2906a 100644 --- a/pkg/pub_integration/lib/src/test_browser.dart +++ b/pkg/pub_integration/lib/src/test_browser.dart @@ -45,7 +45,7 @@ class TestBrowser { final binaries = [ '/usr/bin/google-chrome', ]; - for (String binary in binaries) { + for (final binary in binaries) { if (File(binary).existsSync()) return binary; } diff --git a/pkg/pub_integration/lib/src/test_data.dart b/pkg/pub_integration/lib/src/test_data.dart index b5179b2d0e..f6f1a867f9 100644 --- a/pkg/pub_integration/lib/src/test_data.dart +++ b/pkg/pub_integration/lib/src/test_data.dart @@ -41,7 +41,7 @@ Future _copy(String fromDir, String toDir) async { .where((fse) => fse is File) .cast() .toList(); - for (File file in files) { + for (final file in files) { final relativePath = p.relative(file.path, from: fromDir); final newPath = p.join(toDir, relativePath); final newFile = File(newPath); diff --git a/pkg/web_app/lib/src/hoverable.dart b/pkg/web_app/lib/src/hoverable.dart index bd853b3c72..32421b3eea 100644 --- a/pkg/web_app/lib/src/hoverable.dart +++ b/pkg/web_app/lib/src/hoverable.dart @@ -27,7 +27,7 @@ Element? _activeHover; /// Their `:hover` and `.hover` style must match to have the same effect. void _setEventForHoverable() { document.body!.onClick.listen(deactivateHover); - for (Element h in document.querySelectorAll('.hoverable')) { + for (final h in document.querySelectorAll('.hoverable')) { registerHoverable(h); } } diff --git a/pkg/web_app/lib/src/issues.dart b/pkg/web_app/lib/src/issues.dart index 3fc448c412..6aebdca26f 100644 --- a/pkg/web_app/lib/src/issues.dart +++ b/pkg/web_app/lib/src/issues.dart @@ -13,7 +13,7 @@ void setupIssues() { } void _guardReportIssue() { - for (AnchorElement bugLink in document.querySelectorAll('a.github_issue')) { + for (final bugLink in document.querySelectorAll('a.github_issue')) { bugLink.onClick.listen((event) { if (!window.confirm('This link is for reporting issues for the pub site. ' 'If you would like to report a problem with a package, please visit ' @@ -25,7 +25,8 @@ void _guardReportIssue() { } void _fixIssueLinks() { - for (AnchorElement bugLink in document.querySelectorAll('a.github_issue')) { + for (final bugLink + in document.querySelectorAll('a.github_issue').cast()) { var url = Uri.parse(bugLink.href!); final lines = [ 'URL: ${window.location.href}',