From d9497299f2e3fb38f2b1b00a380325c26240cd3e Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Wed, 14 Sep 2022 10:58:26 +0200 Subject: [PATCH] Migrate tools/licenses to null safety (flutter/engine#35882) --- .../flutter/ci/licenses_golden/tool_signature | 2 +- .../src/flutter/tools/licenses/lib/cache.dart | 8 +- .../tools/licenses/lib/filesystem.dart | 54 +-- .../flutter/tools/licenses/lib/licenses.dart | 190 ++++---- .../src/flutter/tools/licenses/lib/main.dart | 454 +++++++++--------- .../flutter/tools/licenses/lib/patterns.dart | 30 +- .../src/flutter/tools/licenses/pubspec.yaml | 3 +- 7 files changed, 377 insertions(+), 364 deletions(-) diff --git a/engine/src/flutter/ci/licenses_golden/tool_signature b/engine/src/flutter/ci/licenses_golden/tool_signature index 74aacad9829..6ae74cafe6c 100644 --- a/engine/src/flutter/ci/licenses_golden/tool_signature +++ b/engine/src/flutter/ci/licenses_golden/tool_signature @@ -1,2 +1,2 @@ -Signature: d232ec47cb6d61b7385bf1ef936a93c4 +Signature: 647326c44237e255694c24deb9896c68 diff --git a/engine/src/flutter/tools/licenses/lib/cache.dart b/engine/src/flutter/tools/licenses/lib/cache.dart index 23f67e65754..ac0b311bf82 100644 --- a/engine/src/flutter/tools/licenses/lib/cache.dart +++ b/engine/src/flutter/tools/licenses/lib/cache.dart @@ -6,8 +6,9 @@ Map _cache = {}; const int _maxSize = 10; T cache(Key key, T Function() getter) { - T result = _cache[key] as T; - if (result != null) { + T result; + if (_cache[key] != null) { + result = _cache[key] as T; _cache.remove(key); } else { if (_cache.length == _maxSize) { @@ -33,8 +34,7 @@ abstract class Key { if (runtimeType != other.runtimeType) { return false; } - return other is Key - && other._value == _value; + return other is Key && other._value == _value; } @override diff --git a/engine/src/flutter/tools/licenses/lib/filesystem.dart b/engine/src/flutter/tools/licenses/lib/filesystem.dart index ce0b7c6ba07..206f7bb2dde 100644 --- a/engine/src/flutter/tools/licenses/lib/filesystem.dart +++ b/engine/src/flutter/tools/licenses/lib/filesystem.dart @@ -69,7 +69,7 @@ bool isMultiLicenseNotice(Reader reader) { } FileType identifyFile(String name, Reader reader) { - List bytes; + List? bytes; if ((path.split(name).reversed.take(6).toList().reversed.join('/') == 'third_party/icu/source/extra/uconv/README') || // This specific ICU README isn't in UTF-8. (path.split(name).reversed.take(6).toList().reversed.join('/') == 'third_party/icu/source/samples/uresb/sr.txt') || // This specific sample contains non-UTF-8 data (unlike other sr.txt files). (path.split(name).reversed.take(2).toList().reversed.join('/') == 'builds/detect.mk') || // This specific freetype sample contains non-UTF-8 data (unlike other .mk files). @@ -351,7 +351,7 @@ abstract class IoNode { // interface abstract class File extends IoNode { - List readBytes(); + List? readBytes(); } // interface @@ -363,7 +363,7 @@ mixin UTF8TextFile implements TextFile { @override String readString() { try { - return cache(UTF8Of(this), () => utf8.decode(readBytes())); + return cache(UTF8Of(this), () => utf8.decode(readBytes()!)); } on FormatException { print(fullName); rethrow; @@ -375,13 +375,13 @@ mixin Latin1TextFile implements TextFile { @override String readString() { return cache(Latin1Of(this), () { - final List bytes = readBytes(); + final List bytes = readBytes()!; if (bytes.any((int byte) => byte == 0x00)) { throw '$fullName contains a U+0000 NULL and is probably not actually encoded as Win1252'; } bool isUTF8 = false; try { - cache(UTF8Of(this), () => utf8.decode(readBytes())); + cache(UTF8Of(this), () => utf8.decode(readBytes()!)); isUTF8 = true; } on FormatException { // Exceptions are fine/expected for non-UTF8 text, which we test for @@ -404,13 +404,13 @@ abstract class Directory extends IoNode { abstract class Link extends IoNode { } mixin ZipFile on File implements Directory { - ArchiveDirectory _root; + ArchiveDirectory? _root; @override Iterable get walk { try { - _root ??= ArchiveDirectory.parseArchive(a.ZipDecoder().decodeBytes(readBytes()), fullName); - return _root.walk; + _root ??= ArchiveDirectory.parseArchive(a.ZipDecoder().decodeBytes(readBytes()!), fullName); + return _root!.walk; } catch (exception) { print('failed to parse archive:\n$fullName'); rethrow; @@ -419,13 +419,13 @@ mixin ZipFile on File implements Directory { } mixin TarFile on File implements Directory { - ArchiveDirectory _root; + ArchiveDirectory? _root; @override Iterable get walk { try { - _root ??= ArchiveDirectory.parseArchive(a.TarDecoder().decodeBytes(readBytes()), fullName); - return _root.walk; + _root ??= ArchiveDirectory.parseArchive(a.TarDecoder().decodeBytes(readBytes()!), fullName); + return _root!.walk; } catch (exception) { print('failed to parse archive:\n$fullName'); rethrow; @@ -434,15 +434,15 @@ mixin TarFile on File implements Directory { } mixin GZipFile on File implements Directory { - InMemoryFile _data; + InMemoryFile? _data; @override Iterable get walk sync* { try { final String innerName = path.basenameWithoutExtension(fullName); - _data ??= InMemoryFile.parse('$fullName!$innerName', a.GZipDecoder().decodeBytes(readBytes())); + _data ??= InMemoryFile.parse('$fullName!$innerName', a.GZipDecoder().decodeBytes(readBytes()!))!; if (_data != null) { - yield _data; + yield _data!; } } catch (exception) { print('failed to parse archive:\n$fullName'); @@ -452,15 +452,15 @@ mixin GZipFile on File implements Directory { } mixin BZip2File on File implements Directory { - InMemoryFile _data; + InMemoryFile? _data; @override Iterable get walk sync* { try { final String innerName = path.basenameWithoutExtension(fullName); - _data ??= InMemoryFile.parse('$fullName!$innerName', a.BZip2Decoder().decodeBytes(readBytes())); + _data ??= InMemoryFile.parse('$fullName!$innerName', a.BZip2Decoder().decodeBytes(readBytes()!))!; if (_data != null) { - yield _data; + yield _data!; } } catch (exception) { print('failed to parse archive:\n$fullName'); @@ -641,8 +641,8 @@ class ArchiveFile extends IoNode implements File { final String fullName; @override - List readBytes() { - return _file.content as List; + List? readBytes() { + return _file.content as List?; } } @@ -676,18 +676,18 @@ class ArchiveBZip2File extends ArchiveFile with BZip2File { class InMemoryFile extends IoNode implements File { InMemoryFile(this.fullName, this._bytes); - static InMemoryFile parse(String fullName, List bytes) { + static InMemoryFile? parse(String fullName, List bytes) { if (bytes.isEmpty) { return null; } switch (identifyFile(fullName, () => bytes)) { - case FileType.binary: return InMemoryFile(fullName, bytes); break; - case FileType.zip: return InMemoryZipFile(fullName, bytes); break; - case FileType.tar: return InMemoryTarFile(fullName, bytes); break; - case FileType.gz: return InMemoryGZipFile(fullName, bytes); break; - case FileType.bzip2: return InMemoryBZip2File(fullName, bytes); break; - case FileType.text: return InMemoryUTF8TextFile(fullName, bytes); break; - case FileType.latin1Text: return InMemoryLatin1TextFile(fullName, bytes); break; + case FileType.binary: return InMemoryFile(fullName, bytes); + case FileType.zip: return InMemoryZipFile(fullName, bytes); + case FileType.tar: return InMemoryTarFile(fullName, bytes); + case FileType.gz: return InMemoryGZipFile(fullName, bytes); + case FileType.bzip2: return InMemoryBZip2File(fullName, bytes); + case FileType.text: return InMemoryUTF8TextFile(fullName, bytes); + case FileType.latin1Text: return InMemoryLatin1TextFile(fullName, bytes); case FileType.metadata: break; // ignore this file } assert(false); diff --git a/engine/src/flutter/tools/licenses/lib/licenses.dart b/engine/src/flutter/tools/licenses/lib/licenses.dart index a8cd70c7fa5..c3544986501 100644 --- a/engine/src/flutter/tools/licenses/lib/licenses.dart +++ b/engine/src/flutter/tools/licenses/lib/licenses.dart @@ -5,8 +5,6 @@ import 'dart:convert'; import 'dart:io' as system; -import 'package:meta/meta.dart'; - import 'cache.dart'; import 'limits.dart'; import 'patterns.dart'; @@ -15,7 +13,7 @@ class FetchedContentsOf extends Key { FetchedContentsOf(dynamic value) : super(v enum LicenseType { unknown, bsd, gpl, lgpl, mpl, afl, mit, freetype, apache, apacheNotice, eclipse, ijg, zlib, icu, apsl, libpng, openssl, vulkan, bison } -LicenseType convertLicenseNameToType(String name) { +LicenseType convertLicenseNameToType(String? name) { switch (name) { case 'Apache': case 'apache-license-2.0': @@ -118,15 +116,15 @@ LicenseType convertBodyToType(String body) { } abstract class LicenseSource { - List nearestLicensesFor(String name); - License nearestLicenseOfType(LicenseType type); - License nearestLicenseWithName(String name, { String authors }); + List? nearestLicensesFor(String name); + License? nearestLicenseOfType(LicenseType type); + License? nearestLicenseWithName(String name, { String? authors }); } abstract class License implements Comparable { factory License.unique(String body, LicenseType type, { bool reformatted = false, - String origin, + String? origin, bool yesWeKnowWhatItLooksLikeButItIsNot = false }) { if (!reformatted) { @@ -144,7 +142,7 @@ abstract class License implements Comparable { factory License.template(String body, LicenseType type, { bool reformatted = false, - String origin + String? origin }) { if (!reformatted) { body = _reformat(body); @@ -161,7 +159,7 @@ abstract class License implements Comparable { factory License.message(String body, LicenseType type, { bool reformatted = false, - String origin + String? origin }) { if (!reformatted) { body = _reformat(body); @@ -176,7 +174,7 @@ abstract class License implements Comparable { return result; } - factory License.blank(String body, LicenseType type, { String origin }) { + factory License.blank(String body, LicenseType type, { String? origin }) { final License result = _registry.putIfAbsent(body, () => BlankLicense._(_reformat(body), type, origin: origin)); assert(() { if (result is! BlankLicense || result.type != type) { @@ -194,7 +192,7 @@ abstract class License implements Comparable { factory License.fromBodyAndType(String body, LicenseType type, { bool reformatted = false, - String origin + String? origin }) { if (!reformatted) { body = _reformat(body); @@ -231,13 +229,12 @@ abstract class License implements Comparable { case LicenseType.bison: return BlankLicense._(body, type, origin: origin); } - return null; }); assert(result.type == type); return result; } - factory License.fromBodyAndName(String body, String name, { String origin }) { + factory License.fromBodyAndName(String body, String name, { String? origin }) { body = _reformat(body); LicenseType type = convertLicenseNameToType(name); if (type == LicenseType.unknown) { @@ -246,18 +243,18 @@ abstract class License implements Comparable { return License.fromBodyAndType(body, type, origin: origin); } - factory License.fromBody(String body, { String origin }) { + factory License.fromBody(String body, { String? origin }) { body = _reformat(body); final LicenseType type = convertBodyToType(body); return License.fromBodyAndType(body, type, reformatted: true, origin: origin); } - factory License.fromCopyrightAndLicense(String copyright, String template, LicenseType type, { String origin }) { + factory License.fromCopyrightAndLicense(String copyright, String? template, LicenseType type, { String? origin }) { final String body = '$copyright\n\n$template'; return _registry.putIfAbsent(body, () => TemplateLicense._(body, type, origin: origin)); } - factory License.fromUrl(String url, { String origin }) { + factory License.fromUrl(String url, { String? origin }) { String body; LicenseType type = LicenseType.unknown; switch (url) { @@ -403,7 +400,7 @@ abstract class License implements Comparable { // if (type == LicenseType.unknown) // print('need detector for:\n----\n$body\n----'); bool isUTF8 = true; - List latin1Encoded; + late List latin1Encoded; try { latin1Encoded = latin1.encode(body); isUTF8 = false; @@ -428,8 +425,8 @@ abstract class License implements Comparable { } final String body; - final String authors; - final String origin; + final String? authors; + final String? origin; final LicenseType type; final Set _licensees = {}; @@ -446,7 +443,7 @@ abstract class License implements Comparable { _libraries.add(libraryName); } - Iterable expandTemplate(String copyright, String licenseBody, { String origin }); + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }); @override int compareTo(License other) => toString().compareTo(other.toString()); @@ -467,7 +464,7 @@ abstract class License implements Comparable { String toStringBody() => body; - String toStringFormal() { + String? toStringFormal() { final List prefixes = _libraries.toList(); prefixes.sort(); return '${prefixes.join('\n')}\n\n$body'; @@ -478,7 +475,7 @@ abstract class License implements Comparable { caseSensitive: false ); - static String _readAuthors(String body) { + static String? _readAuthors(String body) { final List matches = _copyrightForAuthors.allMatches(body).toList(); if (matches.isEmpty) { return null; @@ -516,18 +513,18 @@ String _reformat(String body) { } else if (lines.isEmpty) { return ''; } - final List output = []; - int lastGood; - String previousPrefix; + final List output = []; + int? lastGood; + String? previousPrefix; bool lastWasEmpty = true; for (final String line in lines) { - final Match match = stripDecorations.firstMatch(line); - final String prefix = match.group(1); - String s = match.group(2); + final Match match = stripDecorations.firstMatch(line)!; + final String? prefix = match.group(1); + String? s = match.group(2); if (!lastWasEmpty || s != '') { if (s != '') { if (previousPrefix != null) { - if (previousPrefix.length > prefix.length) { + if (previousPrefix.length > prefix!.length) { // TODO(ianh): Spot check files that hit this. At least one just // has a corrupt license block, which is why this is commented out. //if (previousPrefix.substring(prefix.length).contains(nonSpace)) @@ -560,15 +557,15 @@ class _LineRange { final int start; final int end; final String _body; - String _value; + String? _value; String get value { _value ??= _body.substring(start, end); - return _value; + return _value!; } } Iterable<_LineRange> _walkLinesBackwards(String body, int start) sync* { - int end; + int? end; while (start > 0) { start -= 1; if (body[start] == '\n') { @@ -583,8 +580,8 @@ Iterable<_LineRange> _walkLinesBackwards(String body, int start) sync* { } } -Iterable<_LineRange> _walkLinesForwards(String body, { int start = 0, int end }) sync* { - int startIndex = start == 0 || body[start-1] == '\n' ? start : null; +Iterable<_LineRange> _walkLinesForwards(String body, { int start = 0, int? end }) sync* { + int? startIndex = start == 0 || body[start-1] == '\n' ? start : null; int endIndex = startIndex ?? start; end ??= body.length; while (endIndex < end) { @@ -650,14 +647,15 @@ _SplitLicense _splitLicense(String body, { bool verifyResults = true }) { } end = lines.current.end; final String prefix = firstAuthor.substring(0, subindex); - while (lines.moveNext() && lines.current.value.startsWith(prefix)) { + bool hadMoreLines; + while ((hadMoreLines = lines.moveNext()) && lines.current.value.startsWith(prefix)) { final String nextAuthor = lines.current.value.substring(prefix.length); if (nextAuthor == '' || nextAuthor[0] == ' ' || nextAuthor[0] == '\t') { throw 'unexpectedly ragged author list when looking for copyright'; } end = lines.current.end; } - if (lines.current == null) { + if (!hadMoreLines) { break; } } else if (line.contains(halfCopyrightPattern)) { @@ -697,9 +695,9 @@ class _PartialLicenseMatch { final int split; final int end; final Match _match; - String group(int index) => _match.group(index); - String getAuthors() { - final Match match = authorPattern.firstMatch(getCopyrights()); + String? group(int? index) => _match.group(index!); + String? getAuthors() { + final Match? match = authorPattern.firstMatch(getCopyrights()); if (match != null) { return match.group(1); } @@ -708,16 +706,16 @@ class _PartialLicenseMatch { String getCopyrights() => _body.substring(start, split); String getConditions() => _body.substring(split + 1, end); String getEntireLicense() => _body.substring(start, end); - final bool hasCopyrights; + final bool? hasCopyrights; } -Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, int firstPrefixIndex, int indentPrefixIndex, { bool needsCopyright = true }) sync* { +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 (final Match match in pattern.allMatches(body)) { - assert(match.groupCount >= firstPrefixIndex); - assert(match.groupCount >= indentPrefixIndex); + assert(match.groupCount >= firstPrefixIndex!); + assert(match.groupCount >= indentPrefixIndex!); int start = match.start; - final String fullPrefix = '${match.group(firstPrefixIndex)}${match.group(indentPrefixIndex)}'; + final String fullPrefix = '${match.group(firstPrefixIndex!)}${match.group(indentPrefixIndex!)}'; // first we walk back to the start of the block that has the same prefix (e.g. // the start of this comment block) bool firstLineSpecialComment = false; @@ -765,13 +763,13 @@ Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, i for (final _LineRange range in _walkLinesForwards(body, start: start, end: match.start)) { final String line = range.value; if (firstLineSpecialComment || line.startsWith(fullPrefix)) { - String data; + String? data; if (firstLineSpecialComment) { - data = stripDecorations.firstMatch(line).group(2); + data = stripDecorations.firstMatch(line)!.group(2); } else { data = line.substring(fullPrefix.length); } - if (copyrightStatementLeadingPatterns.any((RegExp pattern) => data.contains(pattern))) { + if (copyrightStatementLeadingPatterns.any((RegExp pattern) => data!.contains(pattern))) { start = range.start; foundAny = true; break; @@ -835,7 +833,7 @@ class _LicenseMatch { final bool missingCopyrights; } -Iterable<_LicenseMatch> _expand(License template, String copyright, String body, int start, int end, { String debug = '', String origin }) sync* { +Iterable<_LicenseMatch> _expand(License template, String copyright, String body, int start, int end, { String debug = '', String? origin }) sync* { final List results = template.expandTemplate(_reformat(copyright), body, origin: origin).toList(); if (results.isEmpty) { throw 'license could not be expanded'; @@ -848,7 +846,7 @@ Iterable<_LicenseMatch> _expand(License template, String copyright, String body, Iterable<_LicenseMatch> _tryNone(String body, String filename, RegExp pattern, LicenseSource parentDirectory) sync* { for (final Match match in pattern.allMatches(body)) { - final List results = parentDirectory.nearestLicensesFor(filename); + final List? results = parentDirectory.nearestLicensesFor(filename); if (results == null || results.isEmpty) { throw 'no default license file found'; } @@ -860,20 +858,20 @@ Iterable<_LicenseMatch> _tryNone(String body, String filename, RegExp pattern, L } } -Iterable<_LicenseMatch> _tryAttribution(String body, RegExp pattern, { String origin }) sync* { +Iterable<_LicenseMatch> _tryAttribution(String body, RegExp pattern, { String? origin }) sync* { 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'); } } -Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferencePattern pattern, LicenseSource parentDirectory, { String origin }) sync* { +Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferencePattern pattern, LicenseSource parentDirectory, { String? origin }) sync* { if (pattern.copyrightIndex != null) { - 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); - final License template = parentDirectory.nearestLicenseWithName(filename, authors: authors); + 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!)!; + final License? template = parentDirectory.nearestLicenseWithName(filename, authors: authors); if (template == null) { throw 'failed to find template $filename in $parentDirectory (authors=$authors)'; } @@ -882,13 +880,13 @@ 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 (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); + 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') { filename = 'modp_b64.cc'; } // it was renamed but other files reference the old name - final License template = parentDirectory.nearestLicenseWithName(filename, authors: authors); + final License? template = parentDirectory.nearestLicenseWithName(filename!, authors: authors); if (template == null) { throw 'failed to find accompanying "$filename" in $parentDirectory\n' @@ -903,10 +901,10 @@ Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferenc } } -Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, LicenseSource parentDirectory, { String origin, bool needsCopyright = true }) sync* { +Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, LicenseSource parentDirectory, { String? origin, bool needsCopyright = true }) sync* { 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); + final License? template = parentDirectory.nearestLicenseOfType(type); if (template == null) { throw 'failed to find accompanying $type license in $parentDirectory'; } @@ -923,22 +921,22 @@ Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, License } } -License _dereferenceLicense(int groupIndex, String Function(int index) group, MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String origin }) { - License result = pattern.checkLocalFirst ? parentDirectory.nearestLicenseWithName(group(groupIndex)) : null; +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 = ''; - if (pattern.versionIndices != null && pattern.versionIndices.containsKey(groupIndex)) { - suffix = ':${group(pattern.versionIndices[groupIndex])}'; + if (pattern.versionIndices != null && pattern.versionIndices!.containsKey(groupIndex)) { + suffix = ':${group(pattern.versionIndices![groupIndex]!)}'; } result = License.fromUrl('${group(groupIndex)}$suffix', origin: origin); } return result; } -Iterable<_LicenseMatch> _tryReferenceByUrl(String body, MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String origin }) sync* { - for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, 1, 2, needsCopyright: false)) { +Iterable<_LicenseMatch> _tryReferenceByUrl(String body, MultipleVersionedLicenseReferencePattern pattern, LicenseSource parentDirectory, { String? origin }) sync* { + for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern!, 1, 2, needsCopyright: false)) { bool isDuplicate = false; - for (final 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; @@ -947,8 +945,8 @@ Iterable<_LicenseMatch> _tryReferenceByUrl(String body, MultipleVersionedLicense } Iterable<_LicenseMatch> _tryInline(String body, RegExp pattern, { - @required bool needsCopyright, - String origin, + required bool needsCopyright, + String? origin, }) sync* { assert(needsCopyright != null); for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: false)) { @@ -956,13 +954,13 @@ Iterable<_LicenseMatch> _tryInline(String body, RegExp pattern, { // "missingCopyrights: true" if our own "needsCopyright" argument is true. // We use a template license here (not unique) because it's not uncommon for files // to reference license blocks in other files, but with their own copyrights. - yield _LicenseMatch(License.fromBody(match.getEntireLicense(), origin: origin), match.start, match.end, debug: '_tryInline', missingCopyrights: needsCopyright && !match.hasCopyrights); + yield _LicenseMatch(License.fromBody(match.getEntireLicense(), origin: origin), match.start, match.end, debug: '_tryInline', missingCopyrights: needsCopyright && !match.hasCopyrights!); } } -Iterable<_LicenseMatch> _tryForwardReferencePattern(String fileContents, ForwardReferencePattern pattern, License template, { String origin }) sync* { - for (final _PartialLicenseMatch match in _findLicenseBlocks(fileContents, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex)) { - if (!template.body.contains(pattern.targetPattern)) { +Iterable<_LicenseMatch> _tryForwardReferencePattern(String fileContents, ForwardReferencePattern pattern, License template, { String? origin }) sync* { + 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' 'license:\n---\n${template.body}\n---\nexpected pattern:\n---\n${pattern.targetPattern}\n---'; @@ -971,7 +969,11 @@ Iterable<_LicenseMatch> _tryForwardReferencePattern(String fileContents, Forward } } -List determineLicensesFor(String fileContents, String filename, LicenseSource parentDirectory, { String origin }) { +List determineLicensesFor(String fileContents, String filename, LicenseSource? parentDirectory, { String? origin }) { + if (parentDirectory == null) { + throw 'Fatal error: determineLicensesFor was called with parentDirectory=null!'; + } + if (fileContents.length > kMaxSize) { fileContents = fileContents.substring(0, kMaxSize); } @@ -986,7 +988,7 @@ List determineLicensesFor(String fileContents, String filename, License results.addAll(csReferencesByUrl.expand((MultipleVersionedLicenseReferencePattern pattern) => _tryReferenceByUrl(fileContents, pattern, parentDirectory, origin: origin))); results.addAll(csLicenses.expand((RegExp pattern) => _tryInline(fileContents, pattern, needsCopyright: true, origin: origin))); results.addAll(csNotices.expand((RegExp pattern) => _tryInline(fileContents, pattern, needsCopyright: false, origin: origin))); - _LicenseMatch usedTemplate; + _LicenseMatch? usedTemplate; if (results.length == 1) { final _LicenseMatch target = results.single; results.addAll(csForwardReferenceLicenses.expand((ForwardReferencePattern pattern) => _tryForwardReferencePattern(fileContents, pattern, target.license, origin: origin))); @@ -1042,7 +1044,7 @@ List determineLicensesFor(String fileContents, String filename, License return results.map((_LicenseMatch entry) => entry.license).toList(); } -License interpretAsRedirectLicense(String fileContents, LicenseSource parentDirectory, { String origin }) { +License? interpretAsRedirectLicense(String fileContents, LicenseSource parentDirectory, { String? origin }) { _SplitLicense split; try { split = _splitLicense(fileContents); @@ -1050,12 +1052,12 @@ License interpretAsRedirectLicense(String fileContents, LicenseSource parentDire return null; } final String body = split.getConditions().trim(); - License result; + License? result; for (final MultipleVersionedLicenseReferencePattern pattern in csReferencesByUrl) { - final Match match = pattern.pattern.matchAsPrefix(body); + final Match? match = pattern.pattern!.matchAsPrefix(body); if (match != null && match.start == 0 && match.end == body.length) { - for (final int index in pattern.licenseIndices) { - final License candidate = _dereferenceLicense(index, match.group, pattern, parentDirectory, origin: origin); + for (final int index in pattern.licenseIndices!) { + final License candidate = _dereferenceLicense(index, match.group as String? Function(int?), 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<------'; } @@ -1068,23 +1070,23 @@ License interpretAsRedirectLicense(String fileContents, LicenseSource parentDire // the kind of license that just wants to show a message (e.g. the JPEG one) class MessageLicense extends License { - MessageLicense._(String body, LicenseType type, { String origin }) : super._(body, type, origin: origin); + MessageLicense._(String body, LicenseType type, { String? origin }) : super._(body, type, origin: origin); @override - Iterable expandTemplate(String copyright, String licenseBody, { String origin }) sync* { + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }) sync* { yield this; } } // the kind of license that says to include the copyright and the license text (e.g. BSD) class TemplateLicense extends License { - TemplateLicense._(String body, LicenseType type, { String origin }) + TemplateLicense._(String body, LicenseType type, { String? origin }) : assert(!body.startsWith('Apache License')), super._(body, type, origin: origin); - String _conditions; + String? _conditions; @override - Iterable expandTemplate(String copyright, String licenseBody, { String origin }) sync* { + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }) sync* { _conditions ??= _splitLicense(body).getConditions(); yield License.fromCopyrightAndLicense(copyright, _conditions, type, origin: '$origin + ${this.origin}'); } @@ -1092,10 +1094,10 @@ class TemplateLicense extends License { // the kind of license that expands to two license blocks a main license and the referring block (e.g. OpenSSL) class MultiLicense extends License { - MultiLicense._(String body, LicenseType type, { String origin }) : super._(body, type, origin: origin); + MultiLicense._(String body, LicenseType type, { String? origin }) : super._(body, type, origin: origin); @override - Iterable expandTemplate(String copyright, String licenseBody, { String origin }) sync* { + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }) sync* { yield License.fromBody(body, origin: '$origin + ${this.origin}'); yield License.fromBody(licenseBody, origin: '$origin + ${this.origin}'); } @@ -1104,24 +1106,24 @@ class MultiLicense extends License { // the kind of license that should not be combined with separate copyright notices class UniqueLicense extends License { UniqueLicense._(String body, LicenseType type, { - String origin, + String? origin, bool yesWeKnowWhatItLooksLikeButItIsNot = false }) : super._(body, type, origin: origin, yesWeKnowWhatItLooksLikeButItIsNot: yesWeKnowWhatItLooksLikeButItIsNot); @override - Iterable expandTemplate(String copyright, String licenseBody, { String origin }) sync* { + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }) sync* { throw 'attempted to expand non-template license with "$copyright"\ntemplate was: $this'; } } // the kind of license that doesn't need to be reported anywhere class BlankLicense extends License { - BlankLicense._(String body, LicenseType type, { String origin }) : super._(body, type, origin: origin); + BlankLicense._(String body, LicenseType type, { String? origin }) : super._(body, type, origin: origin); @override - Iterable expandTemplate(String copyright, String licenseBody, { String origin }) sync* { + Iterable expandTemplate(String copyright, String licenseBody, { String? origin }) sync* { yield this; } @override String toStringBody() => ''; @override - String toStringFormal() => null; + String? toStringFormal() => null; } diff --git a/engine/src/flutter/tools/licenses/lib/main.dart b/engine/src/flutter/tools/licenses/lib/main.dart index 215ee64ea4d..60c3d50bbdc 100644 --- a/engine/src/flutter/tools/licenses/lib/main.dart +++ b/engine/src/flutter/tools/licenses/lib/main.dart @@ -11,20 +11,20 @@ import 'dart:io' as system; import 'dart:math' as math; import 'package:args/args.dart'; +import 'package:collection/collection.dart' + show IterableExtension, IterableNullableExtension; import 'package:crypto/crypto.dart' as crypto; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'filesystem.dart' as fs; import 'licenses.dart'; import 'patterns.dart'; - // REPOSITORY OBJECTS abstract class _RepositoryEntry implements Comparable<_RepositoryEntry> { _RepositoryEntry(this.parent, this.io); - final _RepositoryDirectory parent; + final _RepositoryDirectory? parent; final fs.IoNode io; String get name => io.name; String get libraryName; @@ -39,10 +39,10 @@ abstract class _RepositoryEntry implements Comparable<_RepositoryEntry> { abstract class _RepositoryFile extends _RepositoryEntry { _RepositoryFile(_RepositoryDirectory parent, fs.File io) : super(parent, io); - Iterable get licenses; + Iterable? get licenses; @override - String get libraryName => parent.libraryName; + String get libraryName => parent!.libraryName; fs.File get ioFile => super.io as fs.File; } @@ -84,14 +84,14 @@ class _RepositorySourceFile extends _RepositoryLicensedFile { return ioTextFile.readString().startsWith(_hashBangPattern); } - List _licenses; + List? _licenses; @override Iterable get licenses { if (_licenses != null) { - return _licenses; + return _licenses!; } - String contents; + late String contents; try { contents = ioTextFile.readString(); } on FormatException { @@ -99,34 +99,34 @@ class _RepositorySourceFile extends _RepositoryLicensedFile { system.exit(2); } _licenses = determineLicensesFor(contents, name, parent, origin: '$this'); - if (_licenses == null || _licenses.isEmpty) { - _licenses = parent.nearestLicensesFor(name); - if (_licenses == null || _licenses.isEmpty) { + if (_licenses == null || _licenses!.isEmpty) { + _licenses = parent?.nearestLicensesFor(name); + if (_licenses == null || _licenses!.isEmpty) { throw 'file has no detectable license and no in-scope default license file'; } } - _licenses.sort(); + _licenses!.sort(); for (final License license in licenses) { license.markUsed(io.fullName, libraryName); } - assert(_licenses != null && _licenses.isNotEmpty); - return _licenses; + assert(_licenses != null && _licenses!.isNotEmpty); + return _licenses!; } } class _RepositoryBinaryFile extends _RepositoryLicensedFile { _RepositoryBinaryFile(_RepositoryDirectory parent, fs.File io) : super(parent, io); - List _licenses; + List? _licenses; @override - List get licenses { + List? get licenses { if (_licenses == null) { - _licenses = parent.nearestLicensesFor(name); - if (_licenses == null || _licenses.isEmpty) { + _licenses = parent?.nearestLicensesFor(name); + if (_licenses == null || _licenses!.isEmpty) { throw 'no license file found in scope for ${io.fullName}'; } - for (final License license in licenses) { + for (final License license in licenses!) { license.markUsed(io.fullName, libraryName); } } @@ -134,17 +134,16 @@ class _RepositoryBinaryFile extends _RepositoryLicensedFile { } } - // LICENSES abstract class _RepositoryLicenseFile extends _RepositoryFile { _RepositoryLicenseFile(_RepositoryDirectory parent, fs.File io) : super(parent, io); - List licensesFor(String name); - License licenseOfType(LicenseType type); - License licenseWithName(String name); + List? licensesFor(String name); + License? licenseOfType(LicenseType type); + License? licenseWithName(String name); - License get defaultLicense; + License? get defaultLicense; } abstract class _RepositorySingleLicenseFile extends _RepositoryLicenseFile { @@ -154,7 +153,7 @@ abstract class _RepositorySingleLicenseFile extends _RepositoryLicenseFile { final License license; @override - List licensesFor(String name) { + List? licensesFor(String name) { if (license != null) { return [license]; } @@ -162,7 +161,7 @@ abstract class _RepositorySingleLicenseFile extends _RepositoryLicenseFile { } @override - License licenseWithName(String name) { + License? licenseWithName(String name) { if (this.name == name) { return license; } @@ -181,7 +180,7 @@ class _RepositoryGeneralSingleLicenseFile extends _RepositorySingleLicenseFile { : super(parent, io, License.fromBodyAndName(io.readString(), io.name, origin: io.fullName)); @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { if (type == license.type) { return license; } @@ -194,7 +193,7 @@ class _RepositoryApache4DNoticeFile extends _RepositorySingleLicenseFile { : super(parent, io, _parseLicense(io)); @override - License licenseOfType(LicenseType type) => null; + License? licenseOfType(LicenseType type) => null; static final RegExp _pattern = RegExp( r'^(// ------------------------------------------------------------------\n' @@ -212,7 +211,7 @@ class _RepositoryApache4DNoticeFile extends _RepositorySingleLicenseFile { static License _parseLicense(fs.TextFile io) { final Match match = _pattern.allMatches(io.readString()).single; assert(match.groupCount == 2); - return License.unique(match.group(2), LicenseType.apacheNotice, origin: io.fullName); + return License.unique(match.group(2)!, LicenseType.apacheNotice, origin: io.fullName); } } @@ -221,16 +220,16 @@ class _RepositoryLicenseRedirectFile extends _RepositorySingleLicenseFile { : super(parent, io, license); @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { if (type == license.type) { return license; } return null; } - static _RepositoryLicenseRedirectFile maybeCreateFrom(_RepositoryDirectory parent, fs.TextFile io) { + static _RepositoryLicenseRedirectFile? maybeCreateFrom(_RepositoryDirectory parent, fs.TextFile io) { final String contents = io.readString(); - final License license = interpretAsRedirectLicense(contents, parent, origin: io.fullName); + final License? license = interpretAsRedirectLicense(contents, parent, origin: io.fullName); if (license != null) { return _RepositoryLicenseRedirectFile(parent, io, license); } @@ -243,11 +242,11 @@ class _RepositoryLicenseFileWithLeader extends _RepositorySingleLicenseFile { : super(parent, io, _parseLicense(io, leader)); @override - License licenseOfType(LicenseType type) => null; + License? licenseOfType(LicenseType type) => null; static License _parseLicense(fs.TextFile io, RegExp leader) { final String body = io.readString(); - final Match match = leader.firstMatch(body); + final Match? match = leader.firstMatch(body); if (match == null) { throw 'failed to strip leader from $io\nleader: /$leader/\nbody:\n---\n$body\n---'; } @@ -285,7 +284,7 @@ class _RepositoryReadmeIjgFile extends _RepositorySingleLicenseFile { } @override - License licenseWithName(String name) { + License? licenseWithName(String name) { if (this.name == name) { return license; } @@ -293,7 +292,7 @@ class _RepositoryReadmeIjgFile extends _RepositorySingleLicenseFile { } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { return null; } } @@ -308,15 +307,15 @@ class _RepositoryDartLicenseFile extends _RepositorySingleLicenseFile { ); static License _parseLicense(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + final Match? match = _pattern.firstMatch(io.readString()); if (match == null || match.groupCount != 1) { throw 'unexpected Dart license file contents'; } - return License.template(match.group(1), LicenseType.bsd, origin: io.fullName); + return License.template(match.group(1)!, LicenseType.bsd, origin: io.fullName); } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { return null; } } @@ -336,7 +335,7 @@ class _RepositoryLibPngLicenseFile extends _RepositorySingleLicenseFile { } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { if (type == LicenseType.libpng) { return license; } @@ -358,7 +357,7 @@ class _RepositoryBlankLicenseFile extends _RepositorySingleLicenseFile { } @override - License licenseOfType(LicenseType type) => null; + License? licenseOfType(LicenseType type) => null; } class _RepositoryCatapultApiClientLicenseFile extends _RepositorySingleLicenseFile { @@ -382,15 +381,15 @@ class _RepositoryCatapultApiClientLicenseFile extends _RepositorySingleLicenseFi ); static License _parseLicense(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + final Match? match = _pattern.firstMatch(io.readString()); if (match == null || match.groupCount != 1) { throw 'unexpected apiclient license file contents'; } - return License.fromUrl(match.group(1), origin: io.fullName); + return License.fromUrl(match.group(1)!, origin: io.fullName); } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { return null; } } @@ -416,15 +415,15 @@ class _RepositoryCatapultCoverageLicenseFile extends _RepositorySingleLicenseFil ); static License _parseLicense(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + final Match? match = _pattern.firstMatch(io.readString()); if (match == null || match.groupCount != 1) { throw 'unexpected coverage license file contents'; } - return License.fromUrl(match.group(1), origin: io.fullName); + return License.fromUrl(match.group(1)!, origin: io.fullName); } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { return null; } } @@ -462,40 +461,40 @@ class _RepositoryLibJpegTurboLicense extends _RepositoryLicenseFile { } } - List _licenses; + List? _licenses; @override - List get licenses { + List? get licenses { if (_licenses == null) { - 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 _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); - _licenses.add(zlib.licenses.single); + _licenses!.add(readme.license); + _licenses!.add(main.licenses.single); + _licenses!.add(zlib.licenses.single); } return _licenses; } @override - License licenseWithName(String name) { + License? licenseWithName(String name) { return null; } @override - List licensesFor(String name) { + List? licensesFor(String name) { return licenses; } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { return null; } @override - License get defaultLicense => null; + License? get defaultLicense => null; } class _RepositoryFreetypeLicenseFile extends _RepositoryLicenseFile { @@ -546,37 +545,40 @@ class _RepositoryFreetypeLicenseFile extends _RepositoryLicenseFile { r'--- end of LICENSE\.TXT ---\n*$' ); - static String _parseLicense(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + static String? _parseLicense(fs.TextFile io) { + final Match? match = _pattern.firstMatch(io.readString()); if (match == null || match.groupCount != 1) { throw 'unexpected Freetype license file contents'; } return match.group(1); } - final String _target; - List _targetLicense; + final String? _target; + List? _targetLicense; void _warmCache() { - _targetLicense ??= [parent.nearestLicenseWithName(_target)]; + if (parent != null && _targetLicense == null) { + final License? license = parent!.nearestLicenseWithName(_target); + _targetLicense = [license!]; + } } @override - List licensesFor(String name) { + List? licensesFor(String name) { _warmCache(); return _targetLicense; } @override - License licenseOfType(LicenseType type) => null; + License? licenseOfType(LicenseType type) => null; @override - License licenseWithName(String name) => null; + License? licenseWithName(String name) => null; @override License get defaultLicense { _warmCache(); - return _targetLicense.single; + return _targetLicense!.single; } @override @@ -734,31 +736,31 @@ class _RepositoryIcuLicenseFile extends _RepositoryLicenseFile { } static List _parseLicense(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + final Match? match = _pattern.firstMatch(io.readString()); if (match == null) { throw 'could not parse ICU license file'; } assert(match.groupCount == 14); - if (match.group(10).contains(copyrightMentionPattern) || match.group(11).contains('7.')) { + if (match.group(10)!.contains(copyrightMentionPattern) || match.group(11)!.contains('7.')) { throw 'unexpected copyright in ICU license file'; } - if (!match.group(12).contains(gplExceptionExplanation1) || !match.group(13).contains(gplExceptionExplanation2)) { + if (!match.group(12)!.contains(gplExceptionExplanation1) || !match.group(13)!.contains(gplExceptionExplanation2)) { throw 'did not find GPL exception in GPL-licensed files'; } final List result = [ - License.fromBodyAndType(_dewrap(match.group(1)), LicenseType.unknown, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(2)), LicenseType.icu, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(3)), LicenseType.bsd, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(4)), LicenseType.bsd, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(5)), LicenseType.bsd, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(6)), LicenseType.unknown, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(7)), LicenseType.unknown, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(8)), LicenseType.bsd, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(9)), LicenseType.bsd, origin: io.fullName), - License.fromBodyAndType(_dewrap(match.group(11)), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(1)!), LicenseType.unknown, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(2)!), LicenseType.icu, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(3)!), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(4)!), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(5)!), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(6)!), LicenseType.unknown, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(7)!), LicenseType.unknown, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(8)!), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(9)!), LicenseType.bsd, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(11)!), LicenseType.bsd, origin: io.fullName), // Matches 12 and 13 are for the GPL3 license. However, they are covered by an exemption // (they are exempt because ICU4C includes a configuration script generated by Autoconf) - License.fromBodyAndType(_dewrap(match.group(14)), LicenseType.mit, origin: io.fullName), + License.fromBodyAndType(_dewrap(match.group(14)!), LicenseType.mit, origin: io.fullName), ]; return result; } @@ -800,6 +802,7 @@ Iterable> splitIntList(List data, int boundary) sync* { index = end; return data.sublist(start, end).toList(); } + while (index < data.length) { yield getOne(); } @@ -817,7 +820,7 @@ class _RepositoryMultiLicenseNoticesForFilesFile extends _RepositoryLicenseFile // Files of this type should begin with: // "Notices for files contained in the" // ...then have a second line which is 60 "=" characters - final List> contents = splitIntList(io.readBytes(), 0x0A).toList(); + final List> contents = splitIntList(io.readBytes()!, 0x0A).toList(); if (!ascii.decode(contents[0]).startsWith('Notices for files contained in') || ascii.decode(contents[1]) != '============================================================\n') { throw 'unrecognised syntax: ${io.fullName}'; @@ -860,8 +863,8 @@ class _RepositoryMultiLicenseNoticesForFilesFile extends _RepositoryLicenseFile } @override - List licensesFor(String name) { - final License license = _licenses[name]; + List? licensesFor(String name) { + final License? license = _licenses[name]; if (license != null) { return [license]; } @@ -912,13 +915,13 @@ class _RepositoryCxxStlDualLicenseFile extends _RepositoryLicenseFile { ); static List _parseLicenses(fs.TextFile io) { - final Match match = _pattern.firstMatch(io.readString()); + final Match? match = _pattern.firstMatch(io.readString()); if (match == null || match.groupCount != 2) { throw 'unexpected dual license file contents'; } return [ - License.fromBodyAndType(match.group(1), LicenseType.bsd), - License.fromBodyAndType(match.group(2), LicenseType.mit), + License.fromBodyAndType(match.group(1)!, LicenseType.bsd), + License.fromBodyAndType(match.group(2)!, LicenseType.mit), ]; } @@ -946,11 +949,10 @@ class _RepositoryCxxStlDualLicenseFile extends _RepositoryLicenseFile { Iterable get licenses => _licenses; } - // DIRECTORIES class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { - _RepositoryDirectory(_RepositoryDirectory parent, fs.Directory io) : super(parent, io) { + _RepositoryDirectory(_RepositoryDirectory? parent, fs.Directory io) : super(parent, io) { crawl(); } @@ -1017,8 +1019,8 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { /// directory (a.k.a. buildroot). bool shouldRecurse(fs.IoNode entry) { return !entry.fullName.endsWith('third_party/gn') && - !entry.fullName.endsWith('third_party/gradle') && - !entry.fullName.endsWith('third_party/imgui') && + !entry.fullName.endsWith('third_party/gradle') && + !entry.fullName.endsWith('third_party/imgui') && entry.name != '.ccls-cache' && entry.name != '.cipd' && entry.name != '.git' && @@ -1052,7 +1054,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { if (_RepositoryApache4DNoticeFile.consider(entry)) { return _RepositoryApache4DNoticeFile(this, entry); } else { - _RepositoryFile result; + _RepositoryFile? result; if (entry.name == 'NOTICE') { result = _RepositoryLicenseRedirectFile.maybeCreateFrom(this, entry); } @@ -1076,10 +1078,10 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { int get count => _files.length + _subdirectories.fold(0, (int count, _RepositoryDirectory child) => count + child.count); @override - List nearestLicensesFor(String name) { + List? nearestLicensesFor(String name) { if (_licenses.isEmpty) { if (_canGoUp(null)) { - return parent.nearestLicensesFor('${io.name}/$name'); + return parent?.nearestLicensesFor('${io.name}/$name'); } return null; } @@ -1087,7 +1089,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { return _licenses.single.licensesFor(name); } final List licenses = _licenses.expand((_RepositoryLicenseFile license) sync* { - final List licenses = license.licensesFor(name); + final List? licenses = license.licensesFor(name); if (licenses != null) { yield* licenses; } @@ -1103,8 +1105,8 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } @override - License nearestLicenseOfType(LicenseType type) { - License result = _nearestAncestorLicenseWithType(type); + License? nearestLicenseOfType(LicenseType type) { + License? result = _nearestAncestorLicenseWithType(type); if (result == null) { for (final _RepositoryDirectory directory in _subdirectories) { result = directory._localLicenseWithType(type); @@ -1119,29 +1121,29 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { /// Searches the current and all parent directories (up to the license root) /// for a license of the specified type. - License _nearestAncestorLicenseWithType(LicenseType type) { - final License result = _localLicenseWithType(type); + License? _nearestAncestorLicenseWithType(LicenseType type) { + final License? result = _localLicenseWithType(type); if (result != null) { return result; } if (_canGoUp(null)) { - return parent._nearestAncestorLicenseWithType(type); + return parent?._nearestAncestorLicenseWithType(type); } return null; } /// Searches all subdirectories below the current license root for a license /// of the specified type. - License _fullWalkUpForLicenseWithType(LicenseType type) { + License? _fullWalkUpForLicenseWithType(LicenseType type) { return _canGoUp(null) - ? parent._fullWalkUpForLicenseWithType(type) + ? parent?._fullWalkUpForLicenseWithType(type) : _fullWalkDownForLicenseWithType(type); } /// Searches the current directory and all subdirectories for a license of /// the specified type. - License _fullWalkDownForLicenseWithType(LicenseType type) { - License result = _localLicenseWithType(type); + License? _fullWalkDownForLicenseWithType(LicenseType type) { + License? result = _localLicenseWithType(type); if (result == null) { for (final _RepositoryDirectory directory in _subdirectories) { result = directory._fullWalkDownForLicenseWithType(type); @@ -1154,9 +1156,9 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } /// Searches the current directory for licenses of the specified type. - License _localLicenseWithType(LicenseType type) { + License? _localLicenseWithType(LicenseType type) { final List licenses = _licenses.expand((_RepositoryLicenseFile license) sync* { - final License result = license.licenseOfType(type); + final License? result = license.licenseOfType(type); if (result != null) { yield result; } @@ -1172,8 +1174,8 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } @override - License nearestLicenseWithName(String name, { String authors }) { - License result = _nearestAncestorLicenseWithName(name, authors: authors); + License? nearestLicenseWithName(String? name, {String? authors}) { + License? result = _nearestAncestorLicenseWithName(name, authors: authors); if (result == null) { for (final _RepositoryDirectory directory in _subdirectories) { result = directory._localLicenseWithName(name, authors: authors); @@ -1196,29 +1198,29 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { return result; } - bool _canGoUp(String authors) { - return parent != null && (authors != null || isLicenseRootException || (!isLicenseRoot && !parent.subdirectoriesAreLicenseRoots)); + bool _canGoUp(String? authors) { + return parent != null && (authors != null || isLicenseRootException || (!isLicenseRoot && !parent!.subdirectoriesAreLicenseRoots)); } - License _nearestAncestorLicenseWithName(String name, { String authors }) { - final License result = _localLicenseWithName(name, authors: authors); + License? _nearestAncestorLicenseWithName(String? name, { String? authors }) { + final License? result = _localLicenseWithName(name, authors: authors); if (result != null) { return result; } if (_canGoUp(authors)) { - return parent._nearestAncestorLicenseWithName(name, authors: authors); + return parent?._nearestAncestorLicenseWithName(name, authors: authors); } return null; } - License _fullWalkUpForLicenseWithName(String name, { String authors, bool ignoreCase = false }) { + License? _fullWalkUpForLicenseWithName(String? name, { String? authors, bool ignoreCase = false }) { return _canGoUp(authors) - ? parent._fullWalkUpForLicenseWithName(name, authors: authors, ignoreCase: ignoreCase) + ? parent?._fullWalkUpForLicenseWithName(name, authors: authors, ignoreCase: ignoreCase) : _fullWalkDownForLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); } - License _fullWalkDownForLicenseWithName(String name, { String authors, bool ignoreCase = false }) { - License result = _localLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); + License? _fullWalkDownForLicenseWithName(String? name, { String? authors, bool ignoreCase = false }) { + License? result = _localLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); if (result == null) { for (final _RepositoryDirectory directory in _subdirectories) { result = directory._fullWalkDownForLicenseWithName(name, authors: authors, ignoreCase: ignoreCase); @@ -1244,10 +1246,10 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { return name; } assert(parent != null); - if (parent.subdirectoriesAreLicenseRoots) { + if (parent!.subdirectoriesAreLicenseRoots) { return name; } - return parent.libraryName; + return parent!.libraryName; } /// Overrides isLicenseRoot and parent.subdirectoriesAreLicenseRoots for cases @@ -1257,7 +1259,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { /// to the LICENSE in the root of the repo. bool get isLicenseRootException => false; - License _localLicenseWithName(String name, { String authors, bool ignoreCase = false }) { + License? _localLicenseWithName(String? name, { String? authors, bool ignoreCase = false }) { Map map; if (ignoreCase) { // we get here if we're trying a last-ditch effort at finding a file. @@ -1270,10 +1272,10 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } else { map = _childrenByName; } - final _RepositoryEntry entry = map[name]; - License license; + final _RepositoryEntry? entry = map[name!]; + License? license; if (entry is _RepositoryLicensedFile) { - license = entry.licenses.single; + license = entry.licenses!.single; } else if (entry is _RepositoryLicenseFile) { license = entry.defaultLicense; } else if (entry != null) { @@ -1290,7 +1292,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } _RepositoryEntry getChildByName(String name) { - return _childrenByName[name]; + return _childrenByName[name]!; } Set getLicenses(_Progress progress) { @@ -1302,7 +1304,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { if (file.isIncludedInBuildProducts) { try { progress.label = '$file'; - final List licenses = file.licenses.toList(); + final List licenses = file.licenses!.toList(); assert(licenses != null && licenses.isNotEmpty); result.addAll(licenses); progress.advance(success: true); @@ -1317,7 +1319,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { } } for (final _RepositoryLicenseFile file in _licenses) { - result.addAll(file.licenses); + result.addAll(file.licenses!); } return result; } @@ -1351,7 +1353,7 @@ class _RepositoryDirectory extends _RepositoryEntry implements LicenseSource { Stream> _signatureStream(List<_RepositoryLicensedFile> files) async* { for (final _RepositoryLicensedFile file in files) { yield file.io.fullName.codeUnits; - yield file.ioFile.readBytes(); + yield file.ioFile.readBytes()!; } } @@ -1382,8 +1384,8 @@ class _RepositoryReachOutFile extends _RepositoryLicensedFile { final int offset; @override - List get licenses { - _RepositoryDirectory directory = parent; + List? get licenses { + _RepositoryDirectory? directory = parent; int index = offset; while (index > 1) { if (directory == null) { @@ -1392,7 +1394,7 @@ class _RepositoryReachOutFile extends _RepositoryLicensedFile { directory = directory.parent; index -= 1; } - return directory?.nearestLicensesFor(name); + return directory!.nearestLicensesFor(name); } } @@ -1434,7 +1436,6 @@ class _RepositoryExcludeSubpathDirectory extends _RepositoryDirectory { } } - // WHAT TO CRAWL AND WHAT NOT TO CRAWL class _RepositoryAngleDirectory extends _RepositoryDirectory { @@ -1540,8 +1541,8 @@ class _RepositoryFreetypeSrcGZipDirectory extends _RepositoryDirectory { // use the license in zlib.h. @override - List nearestLicensesFor(String name) { - final License zlib = nearestLicenseWithName('zlib.h'); + List? nearestLicensesFor(String name) { + final License? zlib = nearestLicenseWithName('zlib.h'); assert(zlib != null); if (zlib != null) { return [zlib]; @@ -1550,9 +1551,9 @@ class _RepositoryFreetypeSrcGZipDirectory extends _RepositoryDirectory { } @override - License nearestLicenseOfType(LicenseType type) { + License? nearestLicenseOfType(LicenseType type) { if (type == LicenseType.zlib) { - final License result = nearestLicenseWithName('zlib.h'); + final License? result = nearestLicenseWithName('zlib.h'); assert(result != null); return result; } @@ -1582,10 +1583,10 @@ class _RepositoryFreetypeDirectory extends _RepositoryDirectory { _RepositoryFreetypeDirectory(_RepositoryDirectory parent, fs.Directory io) : super(parent, io); @override - List nearestLicensesFor(String name) { - final List result = super.nearestLicensesFor(name); + List? nearestLicensesFor(String name) { + final List? result = super.nearestLicensesFor(name); if (result == null) { - final License license = nearestLicenseWithName('LICENSE.TXT'); + final License? license = nearestLicenseWithName('LICENSE.TXT'); assert(license != null); if (license != null) { return [license]; @@ -1595,9 +1596,9 @@ class _RepositoryFreetypeDirectory extends _RepositoryDirectory { } @override - License nearestLicenseOfType(LicenseType type) { + License? nearestLicenseOfType(LicenseType type) { if (type == LicenseType.freetype) { - final License result = nearestLicenseWithName('FTL.TXT'); + final License? result = nearestLicenseWithName('FTL.TXT'); assert(result != null); return result; } @@ -1810,17 +1811,17 @@ class _RepositoryLibPngDirectory extends _RepositoryDirectory { @override bool shouldRecurse(fs.IoNode entry) { return entry.name != 'contrib' // not linked in - && entry.name != 'mips' // not linked in - && entry.name != 'powerpc' // not linked in - && entry.name != 'projects' // not linked in - && entry.name != 'scripts' // not linked in - && entry.name != 'tests' // not linked in - && entry.name != 'ANNOUNCE' - && entry.name != 'CHANGES' - && entry.name != 'TODO' - && entry.name != 'TRADEMARK' - && !entry.name.contains(skipFileTypes) - && super.shouldRecurse(entry); + && entry.name != 'mips' // not linked in + && entry.name != 'powerpc' // not linked in + && entry.name != 'projects' // not linked in + && entry.name != 'scripts' // not linked in + && entry.name != 'tests' // not linked in + && entry.name != 'ANNOUNCE' + && entry.name != 'CHANGES' + && entry.name != 'TODO' + && entry.name != 'TRADEMARK' + && !entry.name.contains(skipFileTypes) + && super.shouldRecurse(entry); } } @@ -1830,9 +1831,9 @@ class _RepositoryLibWebpDirectory extends _RepositoryDirectory { @override bool shouldRecurse(fs.IoNode entry) { return entry.name != 'examples' // contains nothing that ends up in the binary executable - && entry.name != 'swig' // not included in our build - && entry.name != 'gradle' // not included in our build - && super.shouldRecurse(entry); + && entry.name != 'swig' // not included in our build + && entry.name != 'gradle' // not included in our build + && super.shouldRecurse(entry); } } @@ -1841,17 +1842,17 @@ class _RepositoryPkgDirectory extends _RepositoryDirectory { @override bool shouldRecurse(fs.IoNode entry) { - return entry.name != 'archive' // contains nothing that ends up in the binary executable - && entry.name != 'equatable' - && entry.name != 'file' - && entry.name != 'flutter_packages' - && entry.name != 'gcloud' - && entry.name != 'googleapis' - && entry.name != 'isolate' - && entry.name != 'platform' - && entry.name != 'process' - && entry.name != 'process_runner' - && entry.name != 'vector_math'; + return entry.name != 'archive' // contains nothing that ends up in the binary executable + && entry.name != 'equatable' + && entry.name != 'file' + && entry.name != 'flutter_packages' + && entry.name != 'gcloud' + && entry.name != 'googleapis' + && entry.name != 'isolate' + && entry.name != 'platform' + && entry.name != 'process' + && entry.name != 'process_runner' + && entry.name != 'vector_math'; } @override @@ -1879,7 +1880,8 @@ class _RepositorySkiaLibWebPDirectory extends _RepositoryDirectory { @override _RepositoryDirectory createSubdirectory(fs.Directory entry) { if (entry.name == 'webp') { - return _RepositoryReachOutDirectory(this, entry, const {'config.h'}, 3); + return _RepositoryReachOutDirectory( + this, entry, const {'config.h'}, 3); } return super.createSubdirectory(entry); } @@ -2232,7 +2234,7 @@ class _RepositoryOpenSSLLicenseFile extends _RepositorySingleLicenseFile { } @override - License licenseOfType(LicenseType type) { + License? licenseOfType(LicenseType type) { if (type == LicenseType.openssl) { return license; } @@ -2447,7 +2449,7 @@ _RelativePathDenylistRepositoryDirectory _createImpellerDirectory(fs.Directory e denylist: [ // TODO(chinmaygarde): Remove stb. // https://github.com/flutter/flutter/issues/97843 - 'third_party/stb', // Currently only used for unit tests, and will be removed. + 'third_party/stb', // Currently only used for unit tests, and will be removed. ], parent: parent, io: entry, @@ -2461,10 +2463,10 @@ _RelativePathDenylistRepositoryDirectory _createLibDirectoryRoot(fs.Directory en return _RelativePathDenylistRepositoryDirectory( rootDir: entry, denylist: [ - 'web_ui/lib/assets/ahem.ttf', // this gitignored file exists only for testing purposes - RegExp(r'web_ui/build/.*'), // this is compiler-generated output - RegExp(r'web_ui/dev/.*'), // these are build tools; they do not end up in Engine artifacts - RegExp(r'web_ui/test/.*'), // tests do not end up in Engine artifacts + 'web_ui/lib/assets/ahem.ttf', // this gitignored file exists only for testing purposes + RegExp(r'web_ui/build/.*'), // this is compiler-generated output + RegExp(r'web_ui/dev/.*'), // these are build tools; they do not end up in Engine artifacts + RegExp(r'web_ui/test/.*'), // tests do not end up in Engine artifacts ], parent: parent, io: entry, @@ -2479,7 +2481,7 @@ _RelativePathDenylistRepositoryDirectory _createWebSdkDirectoryRoot(fs.Directory return _RelativePathDenylistRepositoryDirectory( rootDir: entry, denylist: [ - RegExp(r'web_engine_tester/.*'), // contains test code for the engine itself + RegExp( r'web_engine_tester/.*'), // contains test code for the engine itself ], parent: parent, io: entry, @@ -2491,10 +2493,10 @@ _RelativePathDenylistRepositoryDirectory _createWebSdkDirectoryRoot(fs.Directory /// The path patterns in the [denylist] are specified relative to the [rootDir]. class _RelativePathDenylistRepositoryDirectory extends _RepositoryDirectory { _RelativePathDenylistRepositoryDirectory({ - @required this.rootDir, - @required this.denylist, - @required _RepositoryDirectory parent, - @required fs.Directory io, + required this.rootDir, + required this.denylist, + required _RepositoryDirectory parent, + required fs.Directory io, }) : super(parent, io); /// The directory, relative to which the paths are [denylist]ed. @@ -2609,7 +2611,7 @@ class _RepositoryFlutterTxtDirectory extends _RepositoryDirectory { } class _RepositoryFlutterTxtThirdPartyDirectory extends _RepositoryDirectory { - _RepositoryFlutterTxtThirdPartyDirectory(_RepositoryDirectory parent, fs.Directory io) : super(parent, io); + _RepositoryFlutterTxtThirdPartyDirectory( _RepositoryDirectory parent, fs.Directory io): super(parent, io); @override bool shouldRecurse(fs.IoNode entry) { @@ -2689,21 +2691,20 @@ 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 = findChildDirectory(ioDirectory, 'third_party'); - final fs.Directory skiaNode = findChildDirectory(thirdPartyNode, '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.Directory? findChildDirectory(fs.Directory parent, String name) { + return parent.walk.firstWhereOrNull( (fs.IoNode child) => child.name == name, - orElse: () => null, - ) as fs.Directory; + ) as fs.Directory?; } class _Progress { - _Progress(this.max, {bool quiet = false}) : _quiet = quiet { + _Progress(this.max, {bool? quiet = false}) : _quiet = quiet { // This may happen when a git client contains left-over empty component // directories after DEPS file changes. if (max <= 0) { @@ -2712,7 +2713,7 @@ class _Progress { } final int max; - final bool _quiet; + final bool? _quiet; int get withLicense => _withLicense; int _withLicense = 0; int get withoutLicense => _withoutLicense; @@ -2729,7 +2730,8 @@ class _Progress { update(); } } - void advance({@required bool success}) { + + void advance({required bool success}) { assert(success != null); if (success) { _withLicense += 1; @@ -2738,11 +2740,12 @@ class _Progress { } update(); } - Stopwatch _lastUpdate; + + Stopwatch? _lastUpdate; void update({bool flush = false}) { - if (_lastUpdate == null || _lastUpdate.elapsedMilliseconds > 90 || flush) { + if (_lastUpdate == null || _lastUpdate!.elapsedMilliseconds > 90 || flush) { _lastUpdate ??= Stopwatch(); - if (_quiet) { + if (_quiet!) { system.stderr.write('.'); } else { final String line = toString(); @@ -2752,10 +2755,11 @@ class _Progress { } _lastLength = line.length; } - _lastUpdate.reset(); - _lastUpdate.start(); + _lastUpdate!.reset(); + _lastUpdate!.start(); } } + void flush() => update(flush: true); bool get hadErrors => _withoutLicense > 0; @override @@ -2766,13 +2770,13 @@ class _Progress { } /// Reads the signature from a golden file. -Future _readSignature(String goldenPath) async { +Future _readSignature(String goldenPath) async { try { final system.File goldenFile = system.File(goldenPath); final String goldenSignature = await utf8.decoder.bind(goldenFile.openRead()) .transform(const LineSplitter()).first; final RegExp signaturePattern = RegExp(r'Signature: (\w+)'); - final Match goldenMatch = signaturePattern.matchAsPrefix(goldenSignature); + final Match? goldenMatch = signaturePattern.matchAsPrefix(goldenSignature); if (goldenMatch != null) { return goldenMatch.group(1); } @@ -2793,19 +2797,20 @@ void _writeSignature(String signature, system.IOSink sink) { // Checks for changes to the license tool itself. // // Returns true if changes are detected. -Future _computeLicenseToolChanges(_RepositoryDirectory root, {String goldenSignaturePath, String outputSignaturePath}) async { +Future _computeLicenseToolChanges(_RepositoryDirectory root, { required String goldenSignaturePath, required String outputSignaturePath }) async { system.stderr.writeln('Computing signature for license tool'); - 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 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; final system.IOSink sink = system.File(outputSignaturePath).openWrite(); _writeSignature(toolSignature, sink); await sink.close(); - final String goldenSignature = await _readSignature(goldenSignaturePath); + final String? goldenSignature = await _readSignature(goldenSignaturePath); return toolSignature != goldenSignature; } @@ -2814,14 +2819,14 @@ Future _computeLicenseToolChanges(_RepositoryDirectory root, {String golde /// If [writeSignature] is set, the signature is written to the output file. /// If [force] is set, collection is run regardless of whether or not the signature matches. Future _collectLicensesForComponent(_RepositoryDirectory componentRoot, { - String inputGoldenPath, - String outputGoldenPath, - bool writeSignature, - bool force, - bool quiet, + required String inputGoldenPath, + String? outputGoldenPath, + bool? writeSignature, + required bool force, + bool? quiet, }) async { // Check whether the golden file matches the signature of the current contents of this directory. - final String goldenSignature = await _readSignature(inputGoldenPath); + final String? goldenSignature = await _readSignature(inputGoldenPath); final String signature = await componentRoot.signature; if (!force && goldenSignature == signature) { system.stderr.writeln(' Skipping this component - no change in signature'); @@ -2830,9 +2835,9 @@ Future _collectLicensesForComponent(_RepositoryDirectory componentRoot, { final _Progress progress = _Progress(componentRoot.fileCount, quiet: quiet); - final system.File outFile = system.File(outputGoldenPath); + final system.File outFile = system.File(outputGoldenPath!); final system.IOSink sink = outFile.openWrite(); - if (writeSignature) { + if (writeSignature!) { _writeSignature(signature, sink); } @@ -2867,7 +2872,8 @@ Future _collectLicensesForComponent(_RepositoryDirectory componentRoot, { if (output[index].contains('Version: MPL 1.1/GPL 2.0/LGPL 2.1')) { throw 'Unexpected trilicense block found in: ${usedLicenses[index].origin}'; } - if (output[index].contains('The contents of this file are subject to the Mozilla Public License Version')) { + if (output[index].contains( + 'The contents of this file are subject to the Mozilla Public License Version')) { throw 'Unexpected MPL block found in: ${usedLicenses[index].origin}'; } if (output[index].contains('You should have received a copy of the GNU')) { @@ -2903,10 +2909,9 @@ Future _collectLicensesForComponent(_RepositoryDirectory componentRoot, { await sink.close(); progress.label = 'Done.'; progress.flush(); - system.stderr.writeln(''); + system.stderr.writeln(); } - // MAIN Future main(List arguments) async { @@ -2918,7 +2923,7 @@ 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'] as bool; + 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'); @@ -2957,28 +2962,31 @@ Future main(List arguments) async { } progress.label = 'Dumping results...'; progress.flush(); - final List output = licenses + final List output = licenses .where((License license) => license.isUsed) .map((License license) => license.toStringFormal()) - .where((String text) => text != null) + .whereNotNull() .toList(); output.sort(); print(output.join('\n${"-" * 80}\n')); progress.label = 'Done.'; progress.flush(); - system.stderr.writeln(''); + system.stderr.writeln(); } else { // If changes are detected to the license tool itself, force collection // for all components in order to check we're still generating correct // output. const String toolSignatureFilename = 'tool_signature'; final bool forceRunAll = await _computeLicenseToolChanges( - root, - goldenSignaturePath: path.join(argResults['golden'] as String, toolSignatureFilename), - outputSignaturePath: path.join(argResults['out'] as String, toolSignatureFilename), + root, + 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.'); + system.stderr.writeln( + ' Detected changes to license tool. Forcing license collection for all components.'); } final List usedGoldens = []; @@ -2995,8 +3003,10 @@ Future main(List arguments) async { // For other components, we need a clean repository that does not // contain any state left over from previous components. clearLicenseRegistry(); - componentRoot = _EngineSrcDirectory(rootDirectory).subdirectories - .firstWhere((_RepositoryDirectory dir) => dir.name == component.name); + componentRoot = _EngineSrcDirectory(rootDirectory) + .subdirectories + .firstWhere( + (_RepositoryDirectory dir) => dir.name == component.name); } // Always run the full license check on the flutter tree. The flutter diff --git a/engine/src/flutter/tools/licenses/lib/patterns.dart b/engine/src/flutter/tools/licenses/lib/patterns.dart index 1fa9f4df523..c467461939a 100644 --- a/engine/src/flutter/tools/licenses/lib/patterns.dart +++ b/engine/src/flutter/tools/licenses/lib/patterns.dart @@ -270,13 +270,13 @@ class LicenseFileReferencePattern { this.pattern, this.needsCopyright = true }); - final int firstPrefixIndex; - final int indentPrefixIndex; - final int copyrightIndex; - final int authorIndex; - final int fileIndex; + final int? firstPrefixIndex; + final int? indentPrefixIndex; + final int? copyrightIndex; + final int? authorIndex; + final int? fileIndex; final bool needsCopyright; - final RegExp pattern; + final RegExp? pattern; } final List csReferencesByFilename = [ @@ -632,12 +632,12 @@ class MultipleVersionedLicenseReferencePattern { this.pattern }); - final int firstPrefixIndex; - final int indentPrefixIndex; - final List licenseIndices; + final int? firstPrefixIndex; + final int? indentPrefixIndex; + final List? licenseIndices; final bool checkLocalFirst; - final Map versionIndices; - final RegExp pattern; + final Map? versionIndices; + final RegExp? pattern; } final List csReferencesByUrl = [ @@ -2041,10 +2041,10 @@ final List csFallbacks = [ class ForwardReferencePattern { ForwardReferencePattern({ this.firstPrefixIndex, this.indentPrefixIndex, this.pattern, this.targetPattern }); - final int firstPrefixIndex; - final int indentPrefixIndex; - final RegExp pattern; - final RegExp targetPattern; + final int? firstPrefixIndex; + final int? indentPrefixIndex; + final RegExp? pattern; + final RegExp? targetPattern; } final List csForwardReferenceLicenses = [ diff --git a/engine/src/flutter/tools/licenses/pubspec.yaml b/engine/src/flutter/tools/licenses/pubspec.yaml index 66f934a148b..0a6be05dbe8 100644 --- a/engine/src/flutter/tools/licenses/pubspec.yaml +++ b/engine/src/flutter/tools/licenses/pubspec.yaml @@ -5,7 +5,7 @@ name: licenses publish_to: none environment: - sdk: '>=2.8.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' # Do not add any dependencies that require more than what is provided in # //third_party.pkg, //third_party/dart/pkg, or @@ -22,6 +22,7 @@ dependencies: crypto: any meta: any path: any + collection: ^1.16.0 dependency_overrides: archive: