diff --git a/ci/licenses_golden/tool_signature b/ci/licenses_golden/tool_signature index 556caa7a6538a1f48652757677c7bffd8fef8aaf..097a8a8c23ae2685c096dd02457669835d40ce0d 100644 --- a/ci/licenses_golden/tool_signature +++ b/ci/licenses_golden/tool_signature @@ -1,2 +1,2 @@ -Signature: affc80a35fe2dc9647bf293dd8afcaa7 +Signature: 5754c1ee0193299dad20012e408d4ce2 diff --git a/tools/licenses/analysis_options.yaml b/tools/licenses/analysis_options.yaml index 56f88b45e14702ff2f454014f7a0aa018407ee2f..bd1e0ff0246091a038deffe87b622dbabb3b2408 100644 --- a/tools/licenses/analysis_options.yaml +++ b/tools/licenses/analysis_options.yaml @@ -1,162 +1,5 @@ -# Specify analysis options. -# -# Until there are meta linter rules, each desired lint must be explicitly enabled. -# See: https://github.com/dart-lang/linter/issues/288 -# -# For a list of lints, see: http://dart-lang.github.io/linter/lints/ -# See the configuration guide for more -# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer -# -# There are other similar analysis options files in the flutter repos, -# which should be kept in sync with this file: -# -# - analysis_options.yaml -# - tools/licenses/analysis_options.yaml (this file) -# - https://github.com/flutter/flutter/blob/master/analysis_options_user.yaml -# - https://github.com/flutter/flutter/blob/master/packages/flutter/lib/analysis_options_user.yaml -# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml -# -# This file contains the analysis options used by Flutter tools, such as IntelliJ, -# Android Studio, and the `flutter analyze` command. +include: ../../analysis_options.yaml analyzer: - strong-mode: - implicit-dynamic: false errors: - # allow having TODOs in the code - todo: ignore - -linter: - rules: - # these rules are documented on and in the same order as - # the Dart Lint rules page to make maintenance easier - # https://github.com/dart-lang/linter/blob/master/example/all.yaml - - always_declare_return_types - - always_put_control_body_on_new_line - - always_put_required_named_parameters_first - - always_require_non_null_named_parameters - - always_specify_types - - annotate_overrides - # - avoid_annotating_with_dynamic # conflicts with always_specify_types - - avoid_as - - avoid_bool_literals_in_conditional_expressions - # - avoid_catches_without_on_clauses # we do this commonly - # - avoid_catching_errors # we do this commonly - - avoid_classes_with_only_static_members - # - avoid_double_and_int_checks # only useful when targeting JS runtime - - avoid_empty_else - - avoid_field_initializers_in_const_classes - - avoid_function_literals_in_foreach_calls - - avoid_implementing_value_types - - avoid_init_to_null - # - avoid_js_rounded_ints # only useful when targeting JS runtime - - avoid_null_checks_in_equality_operators - - avoid_positional_boolean_parameters - # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - # - avoid_returning_null # there are plenty of valid reasons to return null - - avoid_returning_null_for_void - # - avoid_returning_this # there are plenty of valid reasons to return this - - avoid_setters_without_getters - - avoid_single_cascade_in_expression_statements - - avoid_slow_async_io - - avoid_types_as_parameter_names - # - avoid_types_on_closure_parameters # conflicts with always_specify_types - - avoid_unused_constructor_parameters - - avoid_void_async - - await_only_futures - - camel_case_types - - cancel_subscriptions - # - cascade_invocations # not yet tested - # - close_sinks # not reliable enough - # - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 - # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 - - control_flow_in_finally - # - curly_braces_in_flow_control_structures # not yet tested - # TODO: Re-enable directives_ordering once roll https://github.com/flutter/engine/pull/27324 has completed. - # - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - file_names - - flutter_style_todos - - hash_and_equals - - implementation_imports - # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 - - iterable_contains_unrelated_type - # - join_return_with_assignment # not yet tested - - library_names - - library_prefixes - # - lines_longer_than_80_chars # not yet tested - - list_remove_unrelated_type - # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 - - no_adjacent_strings_in_list - - no_duplicate_case_values - - non_constant_identifier_names - - null_closures - # - omit_local_variable_types # opposite of always_specify_types - # - one_member_abstracts # too many false positives - # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - # - parameter_assignments # we do this commonly - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - # - prefer_constructors_over_static_methods # not yet tested - - prefer_contains - - prefer_equal_for_default_values - # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods - - prefer_final_fields - - prefer_final_locals - - prefer_foreach - - prefer_function_declarations_over_variables # not yet tested - - prefer_generic_function_type_aliases - - prefer_initializing_formals - - prefer_int_literals - # - prefer_interpolation_to_compose_strings # not yet tested - - prefer_is_empty - - prefer_is_not_empty - - prefer_iterable_whereType - # - prefer_mixin # https://github.com/dart-lang/language/issues/32 - - prefer_single_quotes - - prefer_typing_uninitialized_variables - - prefer_void_to_null - # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml - - recursive_getters - - slash_for_doc_comments - - sort_constructors_first - - sort_pub_dependencies - - sort_unnamed_constructors_first - - test_types_in_equals - - throw_in_finally - # - type_annotate_public_apis # subset of always_specify_types - - type_init_formals - # - unawaited_futures # too many false positives - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_getters_setters - # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 - - unnecessary_new - - unnecessary_null_aware_assignments - - unnecessary_null_in_if_null_operators - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_rethrow_when_possible - - use_setters_to_change_properties - # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 - # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - - valid_regexps - - void_checks + public_member_api_docs: ignore diff --git a/tools/licenses/lib/cache.dart b/tools/licenses/lib/cache.dart index 043158b662b5a4fa89baf60742885994a2ad29fa..960baffb4d499c26839536ec5a0a6bcca6aae17b 100644 --- a/tools/licenses/lib/cache.dart +++ b/tools/licenses/lib/cache.dart @@ -5,8 +5,8 @@ Map _cache = {}; const int _maxSize = 10; -T cache(Key key, T getter()) { - T result = _cache[key]; +T cache(Key key, T Function() getter) { + T result = _cache[key] as T; if (result != null) { _cache.remove(key); } else { diff --git a/tools/licenses/lib/filesystem.dart b/tools/licenses/lib/filesystem.dart index 12985db17d4b545cdf05e9a57beeaa736d08d2b1..6295422f0bdaa13307f5ddd9b66bef665e07aa72 100644 --- a/tools/licenses/lib/filesystem.dart +++ b/tools/licenses/lib/filesystem.dart @@ -451,14 +451,14 @@ class FileSystemDirectory extends IoNode implements Directory { Iterable get walk sync* { final List list = _directory.listSync().toList(); list.sort((io.FileSystemEntity a, io.FileSystemEntity b) => a.path.compareTo(b.path)); - for (io.FileSystemEntity entity in list) { + for (final io.FileSystemEntity entity in list) { if (entity is io.Directory) { yield FileSystemDirectory(entity); } else if (entity is io.Link) { yield FileSystemLink(entity); } else { assert(entity is io.File); - final io.File fileEntity = entity; + final io.File fileEntity = entity as io.File; if (fileEntity.lengthSync() > 0) { switch (identifyFile(fileEntity.path, () => _readBytes(fileEntity))) { case FileType.binary: yield FileSystemFile(fileEntity); break; @@ -554,7 +554,7 @@ class ArchiveDirectory extends IoNode implements Directory { } else { if (entry.size > 0) { final String entryFullName = fullName + '/' + path.basename(entry.name); - switch (identifyFile(entry.name, () => entry.content)) { + switch (identifyFile(entry.name, () => entry.content as List)) { case FileType.binary: _files.add(ArchiveFile(entryFullName, entry)); break; case FileType.zip: _files.add(ArchiveZipFile(entryFullName, entry)); break; case FileType.tar: _files.add(ArchiveTarFile(entryFullName, entry)); break; @@ -570,7 +570,7 @@ class ArchiveDirectory extends IoNode implements Directory { static ArchiveDirectory parseArchive(a.Archive archive, String ownerPath) { final ArchiveDirectory root = ArchiveDirectory('$ownerPath!', ''); - for (a.ArchiveFile file in archive.files) { + for (final a.ArchiveFile file in archive.files) { if (file.size > 0) root._add(file, file.name.split('/')); } @@ -597,7 +597,7 @@ class ArchiveFile extends IoNode implements File { @override List readBytes() { - return _file.content; + return _file.content as List; } } diff --git a/tools/licenses/lib/licenses.dart b/tools/licenses/lib/licenses.dart index d8ee7017e009540c59c951b458741299ea2ad686..a678630e5378bb09e8bc72352e674f84fda67336 100644 --- a/tools/licenses/lib/licenses.dart +++ b/tools/licenses/lib/licenses.dart @@ -368,7 +368,7 @@ abstract class License implements Comparable { yesWeKnowWhatItLooksLikeButItIsNot = true; if (detectedType != LicenseType.unknown && detectedType != type && !yesWeKnowWhatItLooksLikeButItIsNot) - throw 'Created a license of type $type but it looks like $detectedType\.'; + throw 'Created a license of type $type but it looks like $detectedType.'; if (type != LicenseType.apache && type != LicenseType.apacheNotice) { if (!yesWeKnowWhatItLooksLikeButItIsNot && body.contains('Apache')) throw 'Non-Apache license (type=$type, detectedType=$detectedType) contains the word "Apache"; maybe it\'s a notice?:\n---\n$body\n---'; @@ -494,7 +494,7 @@ String _reformat(String body) { int lastGood; String previousPrefix; bool lastWasEmpty = true; - for (String line in lines) { + for (final String line in lines) { final Match match = stripDecorations.firstMatch(line); final String prefix = match.group(1); String s = match.group(2); @@ -668,7 +668,7 @@ class _PartialLicenseMatch { Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, int firstPrefixIndex, int indentPrefixIndex, { bool needsCopyright = true }) sync* { // I tried doing this with one big RegExp initially, but that way lay madness. - for (Match match in pattern.allMatches(body)) { + for (final Match match in pattern.allMatches(body)) { assert(match.groupCount >= firstPrefixIndex); assert(match.groupCount >= indentPrefixIndex); int start = match.start; @@ -678,7 +678,7 @@ Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, i bool firstLineSpecialComment = false; bool lastWasBlank = false; bool foundNonBlank = false; - for (_LineRange range in _walkLinesBackwards(body, start)) { + for (final _LineRange range in _walkLinesBackwards(body, start)) { String line = range.value; bool isBlockCommentLine; if (line.length > 3 && line.endsWith('*/')) { @@ -715,7 +715,7 @@ Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, i // then we walk forward dropping anything until the first line that matches what // we think might be part of a copyright statement bool foundAny = false; - for (_LineRange range in _walkLinesForwards(body, start: start, end: match.start)) { + for (final _LineRange range in _walkLinesForwards(body, start: start, end: match.start)) { final String line = range.value; if (firstLineSpecialComment || line.startsWith(fullPrefix)) { String data; @@ -795,7 +795,7 @@ Iterable<_LicenseMatch> _expand(License template, String copyright, String body, } Iterable<_LicenseMatch> _tryNone(String body, String filename, RegExp pattern, LicenseSource parentDirectory) sync* { - for (Match match in pattern.allMatches(body)) { + for (final Match match in pattern.allMatches(body)) { final List results = parentDirectory.nearestLicensesFor(filename); if (results == null || results.isEmpty) throw 'no default license file found'; @@ -807,7 +807,7 @@ Iterable<_LicenseMatch> _tryNone(String body, String filename, RegExp pattern, L } Iterable<_LicenseMatch> _tryAttribution(String body, RegExp pattern, { String origin }) sync* { - for (Match match in pattern.allMatches(body)) { + for (final Match match in pattern.allMatches(body)) { assert(match.groupCount == 2); yield _LicenseMatch(License.unique('Thanks to ${match.group(2)}.', LicenseType.unknown, origin: origin), match.start, match.end, debug: '_tryAttribution'); } @@ -815,7 +815,7 @@ Iterable<_LicenseMatch> _tryAttribution(String body, RegExp pattern, { String or Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferencePattern pattern, LicenseSource parentDirectory, { String origin }) sync* { if (pattern.copyrightIndex != null) { - for (Match match in pattern.pattern.allMatches(body)) { + for (final Match match in pattern.pattern.allMatches(body)) { final String copyright = match.group(pattern.copyrightIndex); final String authors = pattern.authorIndex != null ? match.group(pattern.authorIndex) : null; final String filename = match.group(pattern.fileIndex); @@ -827,7 +827,7 @@ Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferenc yield* _expand(template, copyright, entireLicense, match.start, match.end, debug: '_tryReferenceByFilename (with explicit copyright) looking for $filename', origin: origin); } } else { - for (_PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex, needsCopyright: pattern.needsCopyright)) { + for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex, needsCopyright: pattern.needsCopyright)) { final String authors = match.getAuthors(); String filename = match.group(pattern.fileIndex); if (filename == 'modp_b64.c') @@ -848,7 +848,7 @@ Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferenc } Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, LicenseSource parentDirectory, { String origin, bool needsCopyright = true }) sync* { - for (_PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: needsCopyright)) { + for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: needsCopyright)) { final LicenseType type = convertLicenseNameToType(match.group(3)); final License template = parentDirectory.nearestLicenseOfType(type); if (template == null) @@ -865,7 +865,7 @@ Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, License } } -License _dereferenceLicense(int groupIndex, String group(int index), MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String origin }) { +License _dereferenceLicense(int groupIndex, String Function(int index) group, MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String origin }) { License result = pattern.checkLocalFirst ? parentDirectory.nearestLicenseWithName(group(groupIndex)) : null; if (result == null) { String suffix = ''; @@ -877,9 +877,9 @@ License _dereferenceLicense(int groupIndex, String group(int index), MultipleVer } Iterable<_LicenseMatch> _tryReferenceByUrl(String body, MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String origin }) sync* { - for (_PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, 1, 2, needsCopyright: false)) { + for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, 1, 2, needsCopyright: false)) { bool isDuplicate = false; - for (int index in pattern.licenseIndices) { + for (final int index in pattern.licenseIndices) { final License result = _dereferenceLicense(index, match.group, pattern, parentDirectory, origin: origin); yield _LicenseMatch(result, match.start, match.end, isDuplicate: isDuplicate, debug: '_tryReferenceByUrl'); isDuplicate = true; @@ -892,7 +892,7 @@ Iterable<_LicenseMatch> _tryInline(String body, RegExp pattern, { String origin, }) sync* { assert(needsCopyright != null); - for (_PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: false)) { + for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: false)) { // We search with "needsCopyright: false" but then create a _LicenseMatch with // "missingCopyrights: true" if our own "needsCopyright" argument is true. // We use a template license here (not unique) because it's not uncommon for files @@ -902,7 +902,7 @@ Iterable<_LicenseMatch> _tryInline(String body, RegExp pattern, { } Iterable<_LicenseMatch> _tryForwardReferencePattern(String fileContents, ForwardReferencePattern pattern, License template, { String origin }) sync* { - for (_PartialLicenseMatch match in _findLicenseBlocks(fileContents, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex)) { + for (final _PartialLicenseMatch match in _findLicenseBlocks(fileContents, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex)) { if (!template.body.contains(pattern.targetPattern)) { throw 'forward license reference to unexpected license\n' @@ -957,11 +957,11 @@ List determineLicensesFor(String fileContents, String filename, License return a.end - b.end; }); int position = 0; - for (_LicenseMatch m in verificationList) { + for (final _LicenseMatch m in verificationList) { if (m.isDuplicate) continue; // some text expanded into multiple licenses, so overlapping is expected if (position > m.start) { - for (_LicenseMatch n in results) + for (final _LicenseMatch n in results) print('license match: ${n.start}..${n.end}, ${n.debug}, first line: ${n.license.body.split("\n").first}'); throw 'overlapping licenses in $filename (one ends at $position, another starts at ${m.start})'; } @@ -984,10 +984,10 @@ License interpretAsRedirectLicense(String fileContents, LicenseSource parentDire } final String body = split.getConditions().trim(); License result; - for (MultipleVersionedLicenseReferencePattern pattern in csReferencesByUrl) { + for (final MultipleVersionedLicenseReferencePattern pattern in csReferencesByUrl) { final Match match = pattern.pattern.matchAsPrefix(body); if (match != null && match.start == 0 && match.end == body.length) { - for (int index in pattern.licenseIndices) { + for (final int index in pattern.licenseIndices) { final License candidate = _dereferenceLicense(index, match.group, pattern, parentDirectory, origin: origin); if (result != null && candidate != null) throw 'Multiple potential matches in interpretAsRedirectLicense in $parentDirectory; body was:\n------8<------\n$fileContents\n------8<------'; diff --git a/tools/licenses/lib/main.dart b/tools/licenses/lib/main.dart index b05c45a965ef89c6280320573c3ca6cfb76a2fb1..2122f20b9e56cc9e1f01c2a531b7b7db9f2734f0 100644 --- a/tools/licenses/lib/main.dart +++ b/tools/licenses/lib/main.dart @@ -44,8 +44,7 @@ abstract class _RepositoryFile extends _RepositoryEntry { @override String get libraryName => parent.libraryName; - @override - fs.File get io => super.io; + fs.File get ioFile => super.io as fs.File; } abstract class _RepositoryLicensedFile extends _RepositoryFile { @@ -76,14 +75,13 @@ abstract class _RepositoryLicensedFile extends _RepositoryFile { class _RepositorySourceFile extends _RepositoryLicensedFile { _RepositorySourceFile(_RepositoryDirectory parent, fs.TextFile io) : super(parent, io); - @override - fs.TextFile get io => super.io; + fs.TextFile get ioTextFile => super.io as fs.TextFile; static final RegExp _hashBangPattern = RegExp(r'^#! *(?:/bin/sh|/bin/bash|/usr/bin/env +(?:python|bash))\b'); @override bool get isShellScript { - return io.readString().startsWith(_hashBangPattern); + return ioTextFile.readString().startsWith(_hashBangPattern); } List _licenses; @@ -94,7 +92,7 @@ class _RepositorySourceFile extends _RepositoryLicensedFile { return _licenses; String contents; try { - contents = io.readString(); + contents = ioTextFile.readString(); } on FormatException { print('non-UTF8 data in $io'); system.exit(2); @@ -106,7 +104,7 @@ class _RepositorySourceFile extends _RepositoryLicensedFile { throw 'file has no detectable license and no in-scope default license file'; } _licenses.sort(); - for (License license in licenses) + for (final License license in licenses) license.markUsed(io.fullName, libraryName); assert(_licenses != null && _licenses.isNotEmpty); return _licenses; @@ -124,7 +122,7 @@ class _RepositoryBinaryFile extends _RepositoryLicensedFile { _licenses = parent.nearestLicensesFor(name); if (_licenses == null || _licenses.isEmpty) throw 'no license file found in scope for ${io.fullName}'; - for (License license in licenses) + for (final License license in licenses) license.markUsed(io.fullName, libraryName); } return _licenses; @@ -450,10 +448,10 @@ class _RepositoryLibJpegTurboLicense extends _RepositoryLicenseFile { @override List get licenses { if (_licenses == null) { - final _RepositoryReadmeIjgFile readme = parent.getChildByName('README.ijg'); - final _RepositorySourceFile main = parent.getChildByName('turbojpeg.c'); - final _RepositoryDirectory simd = parent.getChildByName('simd'); - final _RepositorySourceFile zlib = simd.getChildByName('jsimdext.inc'); + final _RepositoryReadmeIjgFile readme = parent.getChildByName('README.ijg') as _RepositoryReadmeIjgFile; + final _RepositorySourceFile main = parent.getChildByName('turbojpeg.c') as _RepositorySourceFile; + final _RepositoryDirectory simd = parent.getChildByName('simd') as _RepositoryDirectory; + final _RepositorySourceFile zlib = simd.getChildByName('jsimdext.inc') as _RepositorySourceFile; _licenses = []; _licenses.add(readme.license); _licenses.add(main.licenses.single); @@ -566,9 +564,6 @@ class _RepositoryIcuLicenseFile extends _RepositoryLicenseFile { : _licenses = _parseLicense(io), super(parent, io); - @override - fs.TextFile get io => super.io; - final List _licenses; static final RegExp _pattern = RegExp( @@ -759,7 +754,7 @@ class _RepositoryMultiLicenseNoticesForFilesFile extends _RepositoryLicenseFile bodyText = latin1.decode(bodyBytes); } final License license = License.unique(bodyText, LicenseType.unknown, origin: io.fullName); - for (String name in names) { + for (final String name in names) { if (result[name] != null) throw 'conflicting license information for $name in ${io.fullName}'; result[name] = license; @@ -861,8 +856,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { crawl(); } - @override - fs.Directory get io => super.io; + fs.Directory get ioDirectory => super.io as fs.Directory; final List<_RepositoryDirectory> _subdirectories = <_RepositoryDirectory>[]; final List<_RepositoryLicensedFile> _files = <_RepositoryLicensedFile>[]; @@ -876,7 +870,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { static final RegExp _licenseNamePattern = RegExp(r'^(?!.*\.py$)(?!.*(?:no|update)-copyright)(?!.*mh-bsd-gcc).*\b_*(?:license(?!\.html)|copying|copyright|notice|l?gpl|bsd|mpl?|ftl\.txt)_*\b', caseSensitive: false); void crawl() { - for (fs.IoNode entry in io.walk) { + for (final fs.IoNode entry in ioDirectory.walk) { if (shouldRecurse(entry)) { assert(!_childrenByName.containsKey(entry.name)); if (entry is fs.Directory) { @@ -891,7 +885,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { _files.add(child); } else { assert(child is _RepositoryLicenseFile); - _licenses.add(child); + _licenses.add(child as _RepositoryLicenseFile); } _childrenByName[child.name] = child; } catch (e) { @@ -904,7 +898,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } } - for (_RepositoryDirectory child in virtualSubdirectories) { + for (final _RepositoryDirectory child in virtualSubdirectories) { _subdirectories.add(child); _childrenByName[child.name] = child; } @@ -967,9 +961,9 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } } } else if (entry.name == 'NOTICE.txt') { - return _RepositoryMultiLicenseNoticesForFilesFile(this, entry); + return _RepositoryMultiLicenseNoticesForFilesFile(this, entry as fs.File); } else { - return _RepositoryBinaryFile(this, entry); + return _RepositoryBinaryFile(this, entry as fs.File); } } @@ -1002,7 +996,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { License nearestLicenseOfType(LicenseType type) { License result = _nearestAncestorLicenseWithType(type); if (result == null) { - for (_RepositoryDirectory directory in _subdirectories) { + for (final _RepositoryDirectory directory in _subdirectories) { result = directory._localLicenseWithType(type); if (result != null) break; @@ -1036,7 +1030,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { License _fullWalkDownForLicenseWithType(LicenseType type) { License result = _localLicenseWithType(type); if (result == null) { - for (_RepositoryDirectory directory in _subdirectories) { + for (final _RepositoryDirectory directory in _subdirectories) { result = directory._fullWalkDownForLicenseWithType(type); if (result != null) break; @@ -1065,7 +1059,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { License nearestLicenseWithName(String name, { String authors }) { License result = _nearestAncestorLicenseWithName(name, authors: authors); if (result == null) { - for (_RepositoryDirectory directory in _subdirectories) { + for (final _RepositoryDirectory directory in _subdirectories) { result = directory._localLicenseWithName(name, authors: authors); if (result != null) break; @@ -1107,7 +1101,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { License _fullWalkDownForLicenseWithName(String name, { String authors, bool ignoreCase = false }) { License result = _localLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); if (result == null) { - for (_RepositoryDirectory directory in _subdirectories) { + for (final _RepositoryDirectory directory in _subdirectories) { result = directory._fullWalkDownForLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); if (result != null) break; @@ -1177,13 +1171,13 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { Set getLicenses(_Progress progress) { final Set result = {}; - for (_RepositoryDirectory directory in _subdirectories) + for (final _RepositoryDirectory directory in _subdirectories) result.addAll(directory.getLicenses(progress)); - for (_RepositoryLicensedFile file in _files) { + for (final _RepositoryLicensedFile file in _files) { if (file.isIncludedInBuildProducts) { try { progress.label = '$file'; - final List licenses = file.licenses; + final List licenses = file.licenses.toList(); assert(licenses != null && licenses.isNotEmpty); result.addAll(licenses); progress.advance(success: true); @@ -1196,37 +1190,37 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } } } - for (_RepositoryLicenseFile file in _licenses) + for (final _RepositoryLicenseFile file in _licenses) result.addAll(file.licenses); return result; } int get fileCount { int result = 0; - for (_RepositoryLicensedFile file in _files) { + for (final _RepositoryLicensedFile file in _files) { if (file.isIncludedInBuildProducts) result += 1; } - for (_RepositoryDirectory directory in _subdirectories) + for (final _RepositoryDirectory directory in _subdirectories) result += directory.fileCount; return result; } Iterable<_RepositoryLicensedFile> get _signatureFiles sync* { - for (_RepositoryLicensedFile file in _files) { + for (final _RepositoryLicensedFile file in _files) { if (file.isIncludedInBuildProducts) yield file; } - for (_RepositoryDirectory directory in _subdirectories) { + for (final _RepositoryDirectory directory in _subdirectories) { if (directory.includeInSignature) yield* directory._signatureFiles; } } Stream> _signatureStream(List<_RepositoryLicensedFile> files) async* { - for (_RepositoryLicensedFile file in files) { + for (final _RepositoryLicensedFile file in files) { yield file.io.fullName.codeUnits; - yield file.io.readBytes(); + yield file.ioFile.readBytes(); } } @@ -1279,7 +1273,7 @@ class _RepositoryReachOutDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (reachOutFilenames.contains(entry.name)) - return _RepositoryReachOutFile(this, entry, offset); + return _RepositoryReachOutFile(this, entry as fs.File, offset); return super.createFile(entry); } } @@ -1374,7 +1368,7 @@ class _RepositoryFreetypeDocsDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE.TXT') - return _RepositoryFreetypeLicenseFile(this, entry); + return _RepositoryFreetypeLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } @@ -1498,7 +1492,7 @@ class _RepositoryIcuDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE') - return _RepositoryIcuLicenseFile(this, entry); + return _RepositoryIcuLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } } @@ -1554,7 +1548,7 @@ class _RepositoryLibcxxDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE.TXT') - return _RepositoryCxxStlDualLicenseFile(this, entry); + return _RepositoryCxxStlDualLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } } @@ -1586,7 +1580,7 @@ class _RepositoryLibcxxabiDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE.TXT') - return _RepositoryCxxStlDualLicenseFile(this, entry); + return _RepositoryCxxStlDualLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } } @@ -1597,9 +1591,9 @@ class _RepositoryLibJpegDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'README') - return _RepositoryReadmeIjgFile(this, entry); + return _RepositoryReadmeIjgFile(this, entry as fs.TextFile); if (entry.name == 'LICENSE') - return _RepositoryLicenseFileWithLeader(this, entry, RegExp(r'^\(Copied from the README\.\)\n+-+\n+')); + return _RepositoryLicenseFileWithLeader(this, entry as fs.TextFile, RegExp(r'^\(Copied from the README\.\)\n+-+\n+')); return super.createFile(entry); } } @@ -1610,7 +1604,7 @@ class _RepositoryLibJpegTurboDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE.md') - return _RepositoryLibJpegTurboLicense(this, entry); + return _RepositoryLibJpegTurboLicense(this, entry as fs.TextFile); return super.createFile(entry); } @@ -1629,7 +1623,7 @@ class _RepositoryLibPngDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE' || entry.name == 'png.h') - return _RepositoryLibPngLicenseFile(this, entry); + return _RepositoryLibPngLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } @@ -1915,7 +1909,7 @@ class _RepositoryBoringSSLSourceDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE') - return _RepositoryOpenSSLLicenseFile(this, entry); + return _RepositoryOpenSSLLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } @@ -1967,7 +1961,7 @@ class _RepositoryBoringSSLDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'README') - return _RepositoryBlankLicenseFile(this, entry, 'This repository contains the files generated by boringssl for its build.'); + return _RepositoryBlankLicenseFile(this, entry as fs.TextFile, 'This repository contains the files generated by boringssl for its build.'); return super.createFile(entry); } @@ -1985,7 +1979,7 @@ class _RepositoryCatapultThirdPartyApiClientDirectory extends _RepositoryDirecto @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE') - return _RepositoryCatapultApiClientLicenseFile(this, entry); + return _RepositoryCatapultApiClientLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } } @@ -1996,7 +1990,7 @@ class _RepositoryCatapultThirdPartyCoverageDirectory extends _RepositoryDirector @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'NOTICE.txt') - return _RepositoryCatapultCoverageLicenseFile(this, entry); + return _RepositoryCatapultCoverageLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } } @@ -2079,7 +2073,7 @@ class _RepositoryDartDirectory extends _RepositoryDirectory { @override _RepositoryFile createFile(fs.IoNode entry) { if (entry.name == 'LICENSE') - return _RepositoryDartLicenseFile(this, entry); + return _RepositoryDartLicenseFile(this, entry as fs.TextFile); return super.createFile(entry); } @@ -2365,12 +2359,18 @@ class _EngineSrcDirectory extends _RepositoryDirectory { List<_RepositoryDirectory> get virtualSubdirectories { // Skia is updated more frequently than other third party libraries and // is therefore represented as a separate top-level component. - final fs.Directory thirdPartyNode = io.walk.firstWhere((fs.IoNode node) => node.name == 'third_party'); - final fs.IoNode skiaNode = thirdPartyNode.walk.firstWhere((fs.IoNode node) => node.name == 'skia'); + final fs.Directory thirdPartyNode = findChildDirectory(ioDirectory, 'third_party'); + final fs.Directory skiaNode = findChildDirectory(thirdPartyNode, 'skia'); return <_RepositoryDirectory>[_RepositorySkiaDirectory(this, skiaNode)]; } } +fs.Directory findChildDirectory(fs.Directory parent, String name) { + return parent.walk.firstWhere( + (fs.IoNode child) => child.name == name, + orElse: () => null, + ) as fs.Directory; +} class _Progress { _Progress(this.max, {bool quiet = false}) : _quiet = quiet { @@ -2459,9 +2459,9 @@ void _writeSignature(String signature, system.IOSink sink) { // Returns true if changes are detected. Future _computeLicenseToolChanges(_RepositoryDirectory root, {String goldenSignaturePath, String outputSignaturePath}) async { system.stderr.writeln('Computing signature for license tool'); - final fs.Directory flutterNode = root.io.walk.firstWhere((fs.IoNode node) => node.name == 'flutter'); - final fs.Directory toolsNode = flutterNode.walk.firstWhere((fs.IoNode node) => node.name == 'tools'); - final fs.Directory licenseNode = toolsNode.walk.firstWhere((fs.IoNode node) => node.name == 'licenses'); + final fs.Directory flutterNode = findChildDirectory(root.ioDirectory, 'flutter'); + final fs.Directory toolsNode = findChildDirectory(flutterNode, 'tools'); + final fs.Directory licenseNode = findChildDirectory(toolsNode, 'licenses'); final _RepositoryFlutterLicenseToolDirectory licenseToolDirectory = _RepositoryFlutterLicenseToolDirectory(licenseNode); final String toolSignature = await licenseToolDirectory.signature; @@ -2570,8 +2570,8 @@ Future main(List arguments) async { ..addFlag('release', help: 'Print output in the format used for product releases'); final ArgResults argResults = parser.parse(arguments); - final bool quiet = argResults['quiet']; - final bool releaseMode = argResults['release']; + final bool quiet = argResults['quiet'] as bool; + final bool releaseMode = argResults['release'] as bool; if (argResults['src'] == null) { print('Flutter license script: Must provide --src directory'); print(parser.usage); @@ -2583,19 +2583,19 @@ Future main(List arguments) async { print(parser.usage); system.exit(1); } - if (!system.FileSystemEntity.isDirectorySync(argResults['golden'])) { + if (!system.FileSystemEntity.isDirectorySync(argResults['golden'] as String)) { print('Flutter license script: Golden directory does not exist'); print(parser.usage); system.exit(1); } - final system.Directory out = system.Directory(argResults['out']); + final system.Directory out = system.Directory(argResults['out'] as String); if (!out.existsSync()) out.createSync(recursive: true); } try { system.stderr.writeln('Finding files...'); - final fs.FileSystemDirectory rootDirectory = fs.FileSystemDirectory.fromPath(argResults['src']); + final fs.FileSystemDirectory rootDirectory = fs.FileSystemDirectory.fromPath(argResults['src'] as String); final _RepositoryDirectory root = _EngineSrcDirectory(rootDirectory); if (releaseMode) { @@ -2624,15 +2624,15 @@ Future main(List arguments) async { const String toolSignatureFilename = 'tool_signature'; final bool forceRunAll = await _computeLicenseToolChanges( root, - goldenSignaturePath: path.join(argResults['golden'], toolSignatureFilename), - outputSignaturePath: path.join(argResults['out'], toolSignatureFilename), + goldenSignaturePath: path.join(argResults['golden'] as String, toolSignatureFilename), + outputSignaturePath: path.join(argResults['out'] as String, toolSignatureFilename), ); if (forceRunAll) system.stderr.writeln(' Detected changes to license tool. Forcing license collection for all components.'); final List usedGoldens = []; bool isFirstComponent = true; - for (_RepositoryDirectory component in root.subdirectories) { + for (final _RepositoryDirectory component in root.subdirectories) { system.stderr.writeln('Collecting licenses for ${component.io.name}'); _RepositoryDirectory componentRoot; @@ -2655,8 +2655,8 @@ Future main(List arguments) async { final String goldenFileName = 'licenses_${component.io.name}'; await _collectLicensesForComponent( componentRoot, - inputGoldenPath: path.join(argResults['golden'], goldenFileName), - outputGoldenPath: path.join(argResults['out'], goldenFileName), + inputGoldenPath: path.join(argResults['golden'] as String, goldenFileName), + outputGoldenPath: path.join(argResults['out'] as String, goldenFileName), writeSignature: component.io.name != 'flutter', force: forceRunAll || component.io.name == 'flutter', quiet: quiet, @@ -2664,7 +2664,7 @@ Future main(List arguments) async { usedGoldens.add(goldenFileName); } - final Set unusedGoldens = system.Directory(argResults['golden']).listSync() + final Set unusedGoldens = system.Directory(argResults['golden'] as String).listSync() .map((system.FileSystemEntity file) => path.basename(file.path)).toSet() ..removeAll(usedGoldens) ..remove(toolSignatureFilename); diff --git a/tools/licenses/lib/patterns.dart b/tools/licenses/lib/patterns.dart index 644963a4000329d1a6fd28f707957c6b282012bf..d7711d34b85d553cb526eeab8691e8035b55d201 100644 --- a/tools/licenses/lib/patterns.dart +++ b/tools/licenses/lib/patterns.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore_for_file: use_raw_strings + // COMMON PATTERNS const String kIndent = r'^((?:[-;@#