diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 714f3988..47450edb 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -1,4 +1,4 @@ -# Created with package:mono_repo v3.4.6 +# Created with package:mono_repo v3.4.7 name: Dart CI on: push: @@ -27,13 +27,13 @@ jobs: restore-keys: | os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: stable - id: checkout uses: actions/checkout@v2 - name: mono_repo self validate - run: pub global activate mono_repo 3.4.6 + run: pub global activate mono_repo 3.4.7 - name: mono_repo self validate run: pub global run mono_repo generate --validate job_002: @@ -50,7 +50,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: dev - id: checkout @@ -108,7 +108,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: dev - id: checkout @@ -140,7 +140,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: "2.12.0" - id: checkout @@ -155,6 +155,39 @@ jobs: working-directory: source_gen run: dartanalyzer . job_005: + name: "unit_test; Dart 2.12.0; PKG: example_usage; `pub run test --run-skipped`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@v2 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:example_usage;commands:test_0" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;dart:2.12.0;packages:example_usage + os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - uses: dart-lang/setup-dart@v1.0 + with: + sdk: "2.12.0" + - id: checkout + uses: actions/checkout@v2 + - id: example_usage_pub_upgrade + name: "example_usage; pub upgrade --no-precompile" + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: example_usage + run: pub upgrade --no-precompile + - name: "example_usage; pub run test --run-skipped" + if: "always() && steps.example_usage_pub_upgrade.conclusion == 'success'" + working-directory: example_usage + run: pub run test --run-skipped + needs: + - job_001 + - job_002 + - job_003 + - job_004 + job_006: name: "unit_test; Dart dev; PKG: example_usage; `pub run test --run-skipped`" runs-on: ubuntu-latest steps: @@ -168,7 +201,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: dev - id: checkout @@ -187,7 +220,7 @@ jobs: - job_002 - job_003 - job_004 - job_006: + job_007: name: "unit_test; Dart 2.12.0; PKG: source_gen; `pub run test`" runs-on: ubuntu-latest steps: @@ -201,7 +234,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:2.12.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: "2.12.0" - id: checkout @@ -220,7 +253,7 @@ jobs: - job_002 - job_003 - job_004 - job_007: + job_008: name: "unit_test; Dart dev; PKG: source_gen; `pub run test`" runs-on: ubuntu-latest steps: @@ -234,7 +267,7 @@ jobs: os:ubuntu-latest;pub-cache-hosted;dart:dev os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: dev - id: checkout diff --git a/_test_annotations/pubspec.yaml b/_test_annotations/pubspec.yaml index 1e1630d8..9d6dc2a1 100644 --- a/_test_annotations/pubspec.yaml +++ b/_test_annotations/pubspec.yaml @@ -1,3 +1,3 @@ name: _test_annotations environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' diff --git a/example/pubspec.yaml b/example/pubspec.yaml index b60696f3..f394396f 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,10 +1,10 @@ name: source_gen_example environment: - sdk: ">=2.10.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - analyzer: '>=0.42.0-nullsafety <2.0.0' + analyzer: ^1.0.0 build: ^2.0.0 source_gen: any diff --git a/example_usage/mono_pkg.yaml b/example_usage/mono_pkg.yaml index 61b6b022..9fad7538 100644 --- a/example_usage/mono_pkg.yaml +++ b/example_usage/mono_pkg.yaml @@ -1,5 +1,6 @@ # See https://github.com/google/mono_repo.dart for details dart: +- 2.12.0 - dev stages: diff --git a/example_usage/pubspec.yaml b/example_usage/pubspec.yaml index c53f4767..7044eca0 100644 --- a/example_usage/pubspec.yaml +++ b/example_usage/pubspec.yaml @@ -1,11 +1,11 @@ name: source_gen_example_usage environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dev_dependencies: build_runner: ^1.10.3 - build_verify: ^1.1.0 + build_verify: ^2.0.0 source_gen_example: path: ../example test: ^1.5.1 diff --git a/source_gen/CHANGELOG.md b/source_gen/CHANGELOG.md index 0b774500..9240a3c2 100644 --- a/source_gen/CHANGELOG.md +++ b/source_gen/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.0 + +- Migrate to null safety. +- Require Dart `2.12.0`. + ## 0.9.10+4 * Upgrade to `package:build` version `2.0.0`. diff --git a/source_gen/lib/builder.dart b/source_gen/lib/builder.dart index 5fe72ac8..0ad821f4 100644 --- a/source_gen/lib/builder.dart +++ b/source_gen/lib/builder.dart @@ -22,12 +22,12 @@ import 'src/utils.dart'; const _outputExtensions = '.g.dart'; const _partFiles = '.g.part'; -Builder combiningBuilder([BuilderOptions options]) { - final optionsMap = Map.from(options?.config ?? {}); +Builder combiningBuilder([BuilderOptions options = BuilderOptions.empty]) { + final optionsMap = Map.from(options.config); - final includePartName = optionsMap.remove('include_part_name') as bool; + final includePartName = optionsMap.remove('include_part_name') as bool?; final ignoreForFile = Set.from( - optionsMap.remove('ignore_for_file') as List ?? [], + optionsMap.remove('ignore_for_file') as List? ?? [], ); final builder = CombiningBuilder( @@ -36,11 +36,7 @@ Builder combiningBuilder([BuilderOptions options]) { ); if (optionsMap.isNotEmpty) { - if (log == null) { - throw StateError('Upgrade `build_runner` to at least 0.8.2.'); - } else { - log.warning('These options were ignored: `$optionsMap`.'); - } + log.warning('These options were ignored: `$optionsMap`.'); } return builder; } @@ -67,8 +63,8 @@ class CombiningBuilder implements Builder { /// is output as a comment before its content. This can be useful when /// debugging build issues. const CombiningBuilder({ - bool includePartName = false, - Set ignoreForFile, + bool? includePartName, + Set? ignoreForFile, }) : _includePartName = includePartName ?? false, _ignoreForFile = ignoreForFile ?? const {}; @@ -89,7 +85,7 @@ class CombiningBuilder implements Builder { partIdRegExpLiteral, // A valid part ID RegExp.escape(_partFiles), // the ending part extension '\$', // end of string - ].join('')); + ].join()); final assetIds = await buildStep .findAssets(Glob(pattern)) diff --git a/source_gen/lib/src/builder.dart b/source_gen/lib/src/builder.dart index c956a218..2286a261 100644 --- a/source_gen/lib/src/builder.dart +++ b/source_gen/lib/src/builder.dart @@ -41,10 +41,10 @@ class _Builder extends Builder { /// Wrap [_generators] to form a [Builder]-compatible API. _Builder( this._generators, { - String Function(String code) formatOutput, + String Function(String code)? formatOutput, String generatedExtension = '.g.dart', List additionalOutputExtensions = const [], - String header, + String? header, this.allowSyntaxErrors = false, }) : _generatedExtension = generatedExtension, buildExtensions = { @@ -55,9 +55,6 @@ class _Builder extends Builder { }, formatOutput = formatOutput ?? _formatter.format, _header = (header ?? defaultFileHeader).trim() { - if (_generatedExtension == null) { - throw ArgumentError.notNull('generatedExtension'); - } if (_generatedExtension.isEmpty || !_generatedExtension.startsWith('.')) { throw ArgumentError.value(_generatedExtension, 'generatedExtension', 'Extension must be in the format of .*'); @@ -109,14 +106,6 @@ class _Builder extends Builder { if (!_isLibraryBuilder) { final asset = buildStep.inputId; final name = nameOfPartial(library, asset); - if (name == null) { - final suggest = suggestLibraryName(asset); - throw InvalidGenerationSourceError( - 'Could not find library identifier so a "part of" cannot be built.', - todo: '' - 'Consider adding the following to your source file:\n\n' - 'library $suggest;'); - } contentBuffer.writeln(); String part; @@ -212,7 +201,7 @@ class SharedPartBuilder extends _Builder { SharedPartBuilder( List generators, String partId, { - String Function(String code) formatOutput, + String Function(String code)? formatOutput, List additionalOutputExtensions = const [], bool allowSyntaxErrors = false, }) : super( @@ -267,9 +256,9 @@ class PartBuilder extends _Builder { PartBuilder( List generators, String generatedExtension, { - String Function(String code) formatOutput, + String Function(String code)? formatOutput, List additionalOutputExtensions = const [], - String header, + String? header, bool allowSyntaxErrors = false, }) : super( generators, @@ -307,10 +296,10 @@ class LibraryBuilder extends _Builder { /// libraries. LibraryBuilder( Generator generator, { - String Function(String code) formatOutput, + String Function(String code)? formatOutput, String generatedExtension = '.g.dart', List additionalOutputExtensions = const [], - String header, + String? header, bool allowSyntaxErrors = false, }) : super( [generator], @@ -359,7 +348,8 @@ Future _hasAnyTopLevelAnnotations( if (directive.metadata.isNotEmpty) return true; if (directive is PartDirective) { partIds.add( - AssetId.resolve(Uri.parse(directive.uri.stringValue), from: input)); + AssetId.resolve(Uri.parse(directive.uri.stringValue!), from: input), + ); } } for (var declaration in parsed.declarations) { diff --git a/source_gen/lib/src/constants/reader.dart b/source_gen/lib/src/constants/reader.dart index 3a2d6fcf..711255e0 100644 --- a/source_gen/lib/src/constants/reader.dart +++ b/source_gen/lib/src/constants/reader.dart @@ -16,23 +16,11 @@ import 'utils.dart'; /// Unlike [DartObject.getField], the [read] method attempts to access super /// classes for the field value if not found. abstract class ConstantReader { - factory ConstantReader(DartObject object) => - isNullLike(object) ? const _NullConstant() : _DartObjectConstant(object); + factory ConstantReader(DartObject? object) => + isNullLike(object) ? const _NullConstant() : _DartObjectConstant(object!); const ConstantReader._(); - /// Whether this constant is a literal value. - @Deprecated('Use `isLiteral`, will be removed in 0.8.0') - bool get isAny => isLiteral; - - /// Constant as a literal value. - /// - /// Throws [FormatException] if a valid literal value cannot be returned. This - /// is the case if the constant is not a literal or if the literal value - /// is represented at least partially with [DartObject] instances. - @Deprecated('Use `literalValue`, will be removed in 0.8.0') - Object get anyValue => literalValue; - /// Whether this constant is a literal value. bool get isLiteral => true; @@ -41,7 +29,7 @@ abstract class ConstantReader { /// Throws [FormatException] if a valid literal value cannot be returned. This /// is the case if the constant is not a literal or if the literal value /// is represented at least partially with [DartObject] instances. - Object get literalValue => null; + Object? get literalValue => null; /// Underlying object this instance is reading from. DartObject get objectValue; @@ -59,7 +47,7 @@ abstract class ConstantReader { /// Reads [field] from the constant as another constant value. /// /// Unlike [read], returns `null` if the field is not found. - ConstantReader peek(String field); + ConstantReader? peek(String field); /// Whether this constant is a `null` value. bool get isNull => true; @@ -104,7 +92,7 @@ abstract class ConstantReader { bool get isMap => false; /// Constant as a `Map` value. - Map get mapValue; + Map get mapValue; /// Whether this constant represents a `List` value. bool get isList => false; @@ -156,7 +144,7 @@ class _NullConstant extends ConstantReader { Map get mapValue => _throw('Map'); @override - ConstantReader peek(_) => null; + ConstantReader? peek(_) => null; @override ConstantReader read(_) => throw UnsupportedError('Null'); @@ -180,7 +168,7 @@ class _DartObjectConstant extends ConstantReader { const _DartObjectConstant(this.objectValue) : super._(); - T _check(T value, String expected) { + T _check(T? value, String expected) { if (value == null) { throw FormatException('Not an instance of $expected.', objectValue); } @@ -212,7 +200,7 @@ class _DartObjectConstant extends ConstantReader { @override bool instanceOf(TypeChecker checker) => - checker.isAssignableFromType(objectValue.type); + checker.isAssignableFromType(objectValue.type!); @override bool get isNull => isNullLike(objectValue); @@ -251,7 +239,7 @@ class _DartObjectConstant extends ConstantReader { bool get isMap => objectValue.toMapValue() != null; @override - Map get mapValue => + Map get mapValue => _check(objectValue.toMapValue(), 'Map'); @override @@ -274,7 +262,7 @@ class _DartObjectConstant extends ConstantReader { DartType get typeValue => _check(objectValue.toTypeValue(), 'Type'); @override - ConstantReader peek(String field) { + ConstantReader? peek(String field) { final constant = ConstantReader(getFieldRecursive(objectValue, field)); return constant.isNull ? null : constant; } @@ -283,7 +271,7 @@ class _DartObjectConstant extends ConstantReader { ConstantReader read(String field) { final reader = peek(field); if (reader == null) { - assertHasField(objectValue?.type?.element as ClassElement, field); + assertHasField(objectValue.type?.element as ClassElement, field); return const _NullConstant(); } return reader; diff --git a/source_gen/lib/src/constants/revive.dart b/source_gen/lib/src/constants/revive.dart index 3cb82dda..9926f3f2 100644 --- a/source_gen/lib/src/constants/revive.dart +++ b/source_gen/lib/src/constants/revive.dart @@ -5,6 +5,7 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; + // ignore: implementation_imports import 'package:analyzer/src/dart/constant/value.dart'; @@ -19,9 +20,9 @@ import '../utils.dart'; /// **NOTE**: Some returned [Revivable] instances are not representable as valid /// Dart source code (such as referencing private constructors). It is up to the /// build tool(s) using this library to surface error messages to the user. -Revivable reviveInstance(DartObject object, [LibraryElement origin]) { +Revivable reviveInstance(DartObject object, [LibraryElement? origin]) { final objectType = object.type; - Element element = object.type.aliasElement; + Element? element = objectType!.aliasElement; if (element == null) { if (objectType is InterfaceType) { element = objectType.element; @@ -29,8 +30,8 @@ Revivable reviveInstance(DartObject object, [LibraryElement origin]) { element = object.toFunctionValue(); } } - origin ??= element.library; - var url = Uri.parse(urlOfElement(element)); + origin ??= element!.library; + var url = Uri.parse(urlOfElement(element!)); if (element is FunctionElement) { return Revivable._( source: url.removeFragment(), @@ -64,7 +65,7 @@ Revivable reviveInstance(DartObject object, [LibraryElement origin]) { return !result.isPrivate; } - for (final e in origin.definingCompilationUnit.types + for (final e in origin!.definingCompilationUnit.types .expand((t) => t.fields) .where((f) => f.isConst && f.computeConstantValue() == object)) { final result = Revivable._( @@ -88,17 +89,15 @@ Revivable reviveInstance(DartObject object, [LibraryElement origin]) { return result; } } - if (origin != null) { - for (final e in origin.definingCompilationUnit.topLevelVariables.where( - (f) => f.isConst && f.computeConstantValue() == object, - )) { - final result = Revivable._( - source: Uri.parse(urlOfElement(origin)).replace(fragment: ''), - accessor: e.name, - ); - if (tryResult(result)) { - return result; - } + for (final e in origin.definingCompilationUnit.topLevelVariables.where( + (f) => f.isConst && f.computeConstantValue() == object, + )) { + final result = Revivable._( + source: Uri.parse(urlOfElement(origin)).replace(fragment: ''), + accessor: e.name, + ); + if (tryResult(result)) { + return result; } } // We could try and return the "best" result more intelligently. @@ -128,7 +127,7 @@ class Revivable { final Map namedArguments; const Revivable._({ - this.source, + required this.source, this.accessor = '', this.positionalArguments = const [], this.namedArguments = const {}, diff --git a/source_gen/lib/src/constants/utils.dart b/source_gen/lib/src/constants/utils.dart index 989ae0c7..cbb8666d 100644 --- a/source_gen/lib/src/constants/utils.dart +++ b/source_gen/lib/src/constants/utils.dart @@ -9,7 +9,7 @@ import 'package:analyzer/dart/element/element.dart'; /// /// Super types [ClassElement.supertype] are also checked before throwing. void assertHasField(ClassElement root, String name) { - var element = root; + ClassElement? element = root; while (element != null) { final field = element.getField(name); if (field != null) { @@ -26,16 +26,16 @@ void assertHasField(ClassElement root, String name) { } /// Returns whether or not [object] is or represents a `null` value. -bool isNullLike(DartObject object) => object?.isNull != false; +bool isNullLike(DartObject? object) => object?.isNull != false; /// Similar to [DartObject.getField], but traverses super classes. /// /// Returns `null` if ultimately [field] is never found. -DartObject getFieldRecursive(DartObject object, String field) { +DartObject? getFieldRecursive(DartObject? object, String field) { if (isNullLike(object)) { return null; } - final result = object.getField(field); + final result = object!.getField(field); if (isNullLike(result)) { return getFieldRecursive(object.getField('(super)'), field); } diff --git a/source_gen/lib/src/generated_output.dart b/source_gen/lib/src/generated_output.dart index 3f5476c3..57561133 100644 --- a/source_gen/lib/src/generated_output.dart +++ b/source_gen/lib/src/generated_output.dart @@ -9,8 +9,7 @@ class GeneratedOutput { final String generatorDescription; GeneratedOutput(Generator generator, this.output) - : assert(output != null), - assert(output.isNotEmpty), + : assert(output.isNotEmpty), // assuming length check is cheaper than simple string equality assert(output.length == output.trim().length), generatorDescription = _toString(generator); diff --git a/source_gen/lib/src/generator.dart b/source_gen/lib/src/generator.dart index d657ccde..2b66ca0a 100644 --- a/source_gen/lib/src/generator.dart +++ b/source_gen/lib/src/generator.dart @@ -22,7 +22,8 @@ abstract class Generator { /// output is Dart code returned through the Future. If there is nothing to /// generate for this library may return null, or a Future that resolves to /// null or the empty string. - FutureOr generate(LibraryReader library, BuildStep buildStep) => null; + FutureOr generate(LibraryReader library, BuildStep buildStep) => + null; @override String toString() => runtimeType.toString(); @@ -41,10 +42,9 @@ class InvalidGenerationSourceError extends Error { /// The code element associated with this error. /// /// May be `null` if the error had no associated element. - final Element element; + final Element? element; - InvalidGenerationSourceError(this.message, {String todo, this.element}) - : todo = todo ?? ''; + InvalidGenerationSourceError(this.message, {this.todo = '', this.element}); @override String toString() { @@ -52,7 +52,7 @@ class InvalidGenerationSourceError extends Error { if (element != null) { try { - final span = spanForElement(element); + final span = spanForElement(element!); buffer ..writeln() ..writeln(span.start.toolString) diff --git a/source_gen/lib/src/generator_for_annotation.dart b/source_gen/lib/src/generator_for_annotation.dart index a88d2827..6edf426f 100644 --- a/source_gen/lib/src/generator_for_annotation.dart +++ b/source_gen/lib/src/generator_for_annotation.dart @@ -53,7 +53,7 @@ abstract class GeneratorForAnnotation extends Generator { final generatedValue = generateForAnnotatedElement( annotatedElement.element, annotatedElement.annotation, buildStep); await for (var value in normalizeGeneratorOutput(generatedValue)) { - assert(value == null || (value.length == value.trim().length)); + assert(value.length == value.trim().length); values.add(value); } } diff --git a/source_gen/lib/src/library.dart b/source_gen/lib/src/library.dart index e270b911..c9832be6 100644 --- a/source_gen/lib/src/library.dart +++ b/source_gen/lib/src/library.dart @@ -28,7 +28,7 @@ class LibraryReader { /// /// Unlike [LibraryElement.getType], this also correctly traverses identifiers /// that are accessible via one or more `export` directives. - ClassElement findType(String name) { + ClassElement? findType(String name) { final type = element.exportNamespace.get(name); return type is ClassElement ? type : null; } @@ -49,10 +49,12 @@ class LibraryReader { /// All of the declarations in this library annotated with [checker]. Iterable annotatedWith(TypeChecker checker, - {bool throwOnUnresolved}) sync* { + {bool throwOnUnresolved = true}) sync* { for (final element in allElements) { - final annotation = checker.firstAnnotationOf(element, - throwOnUnresolved: throwOnUnresolved); + final annotation = checker.firstAnnotationOf( + element, + throwOnUnresolved: throwOnUnresolved, + ); if (annotation != null) { yield AnnotatedElement(ConstantReader(annotation), element); } @@ -61,7 +63,7 @@ class LibraryReader { /// All of the declarations in this library annotated with exactly [checker]. Iterable annotatedWithExact(TypeChecker checker, - {bool throwOnUnresolved}) sync* { + {bool throwOnUnresolved = true}) sync* { for (final element in allElements) { final annotation = checker.firstAnnotationOfExact(element, throwOnUnresolved: throwOnUnresolved); @@ -81,7 +83,7 @@ class LibraryReader { /// /// This is a typed convenience function for using [pathToUrl], and the same /// API restrictions hold around supported schemes and relative paths. - Uri pathToElement(Element element) => pathToUrl(element.source.uri); + Uri pathToElement(Element element) => pathToUrl(element.source!.uri); /// Returns a [Uri] from the current library to the one provided. /// @@ -120,9 +122,6 @@ class LibraryReader { return assetToPackageUrl(to); } var from = element.source.uri; - if (from == null) { - throw StateError('Current library has no source URL'); - } // Normalize (convert to an asset: URL). from = normalizeUrl(from); if (_isRelative(from, to)) { @@ -165,9 +164,6 @@ class LibraryReader { /// All of the elements representing classes in this library. Iterable get classes => element.units.expand((cu) => cu.types); - @Deprecated('Use classes instead') - Iterable get classElements => classes; - /// All of the elements representing enums in this library. Iterable get enums => element.units.expand((cu) => cu.enums); } diff --git a/source_gen/lib/src/output_helpers.dart b/source_gen/lib/src/output_helpers.dart index 8ccc0348..e9106ac7 100644 --- a/source_gen/lib/src/output_helpers.dart +++ b/source_gen/lib/src/output_helpers.dart @@ -7,7 +7,7 @@ import 'package:async/async.dart'; /// Converts [Future], [Iterable], and [Stream] implementations /// containing [String] to a single [Stream] while ensuring all thrown /// exceptions are forwarded through the return value. -Stream normalizeGeneratorOutput(Object value) { +Stream normalizeGeneratorOutput(Object? value) { if (value == null) { return const Stream.empty(); } else if (value is Future) { @@ -17,7 +17,7 @@ Stream normalizeGeneratorOutput(Object value) { } if (value is Iterable) { - value = Stream.fromIterable(value as Iterable); + value = Stream.fromIterable(value); } if (value is Stream) { @@ -26,7 +26,7 @@ Stream normalizeGeneratorOutput(Object value) { return e.trim(); } - throw _argError(e); + throw _argError(e as Object); }).where((e) => e.isNotEmpty); } throw _argError(value); diff --git a/source_gen/lib/src/span_for_element.dart b/source_gen/lib/src/span_for_element.dart index 14398b16..2dada576 100644 --- a/source_gen/lib/src/span_for_element.dart +++ b/source_gen/lib/src/span_for_element.dart @@ -18,10 +18,10 @@ import 'utils.dart'; /// /// Not all results from the analyzer API may return source information as part /// of the element, so [file] may need to be manually provided in those cases. -SourceSpan spanForElement(Element element, [SourceFile file]) { - final url = assetToPackageUrl(element.source.uri); +SourceSpan spanForElement(Element element, [SourceFile? file]) { + final url = assetToPackageUrl(element.source!.uri); if (file == null) { - final contents = element?.source?.contents; + final contents = element.source?.contents; if (contents == null) { return SourceSpan( SourceLocation( @@ -32,7 +32,7 @@ SourceSpan spanForElement(Element element, [SourceFile file]) { element.nameOffset + element.nameLength, sourceUrl: url, ), - element.name, + element.name!, ); } file = SourceFile.fromString(contents.data, url: url); @@ -40,11 +40,11 @@ SourceSpan spanForElement(Element element, [SourceFile file]) { if (element.nameOffset < 0) { if (element is PropertyInducingElement) { if (element.getter != null) { - return spanForElement(element.getter); + return spanForElement(element.getter!); } if (element.setter != null) { - return spanForElement(element.setter); + return spanForElement(element.setter!); } } } diff --git a/source_gen/lib/src/type_checker.dart b/source_gen/lib/src/type_checker.dart index 749621ec..70a67ea0 100644 --- a/source_gen/lib/src/type_checker.dart +++ b/source_gen/lib/src/type_checker.dart @@ -4,6 +4,7 @@ import 'dart:mirrors' hide SourceLocation; +import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; @@ -59,7 +60,10 @@ abstract class TypeChecker { /// Otherwise returns `null`. /// /// Throws on unresolved annotations unless [throwOnUnresolved] is `false`. - DartObject firstAnnotationOf(Element element, {bool throwOnUnresolved}) { + DartObject? firstAnnotationOf( + Element element, { + bool throwOnUnresolved = true, + }) { if (element.metadata.isEmpty) { return null; } @@ -71,14 +75,17 @@ abstract class TypeChecker { /// Returns if a constant annotating [element] is assignable to this type. /// /// Throws on unresolved annotations unless [throwOnUnresolved] is `false`. - bool hasAnnotationOf(Element element, {bool throwOnUnresolved}) => + bool hasAnnotationOf(Element element, {bool throwOnUnresolved = true}) => firstAnnotationOf(element, throwOnUnresolved: throwOnUnresolved) != null; /// Returns the first constant annotating [element] that is exactly this type. /// /// Throws [UnresolvedAnnotationException] on unresolved annotations unless /// [throwOnUnresolved] is explicitly set to `false` (default is `true`). - DartObject firstAnnotationOfExact(Element element, {bool throwOnUnresolved}) { + DartObject? firstAnnotationOfExact( + Element element, { + bool throwOnUnresolved = true, + }) { if (element.metadata.isEmpty) { return null; } @@ -91,16 +98,15 @@ abstract class TypeChecker { /// /// Throws [UnresolvedAnnotationException] on unresolved annotations unless /// [throwOnUnresolved] is explicitly set to `false` (default is `true`). - bool hasAnnotationOfExact(Element element, {bool throwOnUnresolved}) => + bool hasAnnotationOfExact(Element element, {bool throwOnUnresolved = true}) => firstAnnotationOfExact(element, throwOnUnresolved: throwOnUnresolved) != null; - DartObject _computeConstantValue( + DartObject? _computeConstantValue( Element element, int annotationIndex, { - bool throwOnUnresolved, + bool throwOnUnresolved = true, }) { - throwOnUnresolved ??= true; final annotation = element.metadata[annotationIndex]; final result = annotation.computeConstantValue(); if (result == null && throwOnUnresolved) { @@ -115,7 +121,7 @@ abstract class TypeChecker { /// [throwOnUnresolved] is explicitly set to `false` (default is `true`). Iterable annotationsOf( Element element, { - bool throwOnUnresolved, + bool throwOnUnresolved = true, }) => _annotationsWhere( element, @@ -126,7 +132,7 @@ abstract class TypeChecker { Iterable _annotationsWhere( Element element, bool Function(DartType) predicate, { - bool throwOnUnresolved, + bool throwOnUnresolved = true, }) sync* { for (var i = 0; i < element.metadata.length; i++) { final value = _computeConstantValue( @@ -134,7 +140,7 @@ abstract class TypeChecker { i, throwOnUnresolved: throwOnUnresolved, ); - if (value?.type != null && predicate(value.type)) { + if (value?.type != null && predicate(value!.type!)) { yield value; } } @@ -146,7 +152,7 @@ abstract class TypeChecker { /// [throwOnUnresolved] is explicitly set to `false` (default is `true`). Iterable annotationsOfExact( Element element, { - bool throwOnUnresolved, + bool throwOnUnresolved = true, }) => _annotationsWhere( element, @@ -161,13 +167,13 @@ abstract class TypeChecker { /// Returns `true` if [staticType] can be assigned to this type. bool isAssignableFromType(DartType staticType) => - isAssignableFrom(staticType.element); + isAssignableFrom(staticType.element!); /// Returns `true` if representing the exact same class as [element]. bool isExactly(Element element); /// Returns `true` if representing the exact same type as [staticType]. - bool isExactlyType(DartType staticType) => isExactly(staticType.element); + bool isExactlyType(DartType staticType) => isExactly(staticType.element!); /// Returns `true` if representing a super class of [element]. /// @@ -178,7 +184,7 @@ abstract class TypeChecker { var theSuper = element.supertype; do { - if (isExactlyType(theSuper)) { + if (isExactlyType(theSuper!)) { return true; } @@ -193,7 +199,7 @@ abstract class TypeChecker { /// /// This only takes into account the *extends* hierarchy. If you wish /// to check mixins and interfaces, use [isAssignableFromType]. - bool isSuperTypeOf(DartType staticType) => isSuperOf(staticType.element); + bool isSuperTypeOf(DartType staticType) => isSuperOf(staticType.element!); } // Checks a static type against another static type; @@ -207,7 +213,7 @@ class _LibraryTypeChecker extends TypeChecker { element is ClassElement && element == _type.element; @override - String toString() => urlOfElement(_type.element); + String toString() => urlOfElement(_type.element!); } // Checks a runtime type against a static type. @@ -287,23 +293,25 @@ class UnresolvedAnnotationException implements Exception { /// Source span of the annotation that was not resolved. /// /// May be `null` if the import library was not found. - final SourceSpan annotationSource; + final SourceSpan? annotationSource; static SourceSpan _findSpan( Element annotatedElement, int annotationIndex, ) { - final parsedLibrary = annotatedElement.session - .getParsedLibraryByElement(annotatedElement.library); - final declaration = parsedLibrary.getElementDeclaration(annotatedElement); + final parsedLibrary = annotatedElement.session! + .getParsedLibraryByElement(annotatedElement.library!); + final declaration = parsedLibrary.getElementDeclaration(annotatedElement) + as ElementDeclarationResult; final annotatedNode = declaration.node as AnnotatedNode; final annotation = annotatedNode.metadata[annotationIndex]; final start = annotation.offset; final end = start + annotation.length; + final parsedUnit = declaration.parsedUnit!; return SourceSpan( - SourceLocation(start, sourceUrl: declaration.parsedUnit.uri), - SourceLocation(end, sourceUrl: declaration.parsedUnit.uri), - declaration.parsedUnit.content.substring(start, end), + SourceLocation(start, sourceUrl: parsedUnit.uri), + SourceLocation(end, sourceUrl: parsedUnit.uri), + parsedUnit.content.substring(start, end), ); } @@ -326,7 +334,7 @@ class UnresolvedAnnotationException implements Exception { String toString() { final message = 'Could not resolve annotation for $annotatedElement'; if (annotationSource != null) { - return annotationSource.message(message); + return annotationSource!.message(message); } return message; } diff --git a/source_gen/lib/src/utils.dart b/source_gen/lib/src/utils.dart index 6c95f30d..6119e616 100644 --- a/source_gen/lib/src/utils.dart +++ b/source_gen/lib/src/utils.dart @@ -38,8 +38,8 @@ String typeNameOf(DartType type) { /// /// Returns `null` if [element] is missing identifier. String nameOfPartial(LibraryElement element, AssetId source) { - if (element.name != null && element.name.isNotEmpty) { - return element.name; + if (element.name != null && element.name!.isNotEmpty) { + return element.name!; } final sourceUrl = p.basename(source.uri.toString()); @@ -69,7 +69,7 @@ String computePartUrl(AssetId input, AssetId output) => String urlOfElement(Element element) => element.kind == ElementKind.DYNAMIC ? 'dart:core#dynamic' // using librarySource.uri – in case the element is in a part - : normalizeUrl(element.librarySource.uri) + : normalizeUrl(element.librarySource!.uri) .replace(fragment: element.name) .toString(); diff --git a/source_gen/pubspec.yaml b/source_gen/pubspec.yaml index 3ff1adb5..38e22f31 100644 --- a/source_gen/pubspec.yaml +++ b/source_gen/pubspec.yaml @@ -1,18 +1,18 @@ name: source_gen -version: 0.9.10+4 +version: 1.0.0 description: >- Source code generation builders and utilities for the Dart build system repository: https://github.com/dart-lang/source_gen environment: - sdk: ">=2.11.999 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - analyzer: '>=0.42.0 <2.0.0' + analyzer: ^1.1.0 async: ^2.0.7 build: ^2.0.0 - dart_style: ^1.0.0 - glob: ">=1.1.0 <3.0.0" + dart_style: ^2.0.0 + glob: ^2.0.0 meta: ^1.1.0 path: ^1.3.2 pedantic: ^1.0.0 diff --git a/source_gen/test/builder_test.dart b/source_gen/test/builder_test.dart index 42c2a065..057ee3a8 100644 --- a/source_gen/test/builder_test.dart +++ b/source_gen/test/builder_test.dart @@ -617,25 +617,25 @@ Future _generateTest(CommentGenerator gen, String expectedContent) async { } Map _createPackageStub( - {String testLibContent, String testLibPartContent}) => + {String? testLibContent, String? testLibPartContent}) => { '$_pkgName|lib/test_lib.dart': testLibContent ?? _testLibContent, '$_pkgName|lib/test_lib.foo.dart': testLibPartContent ?? _testLibPartContent, }; -PartBuilder _unformattedLiteral([String content]) => +PartBuilder _unformattedLiteral([String? content]) => PartBuilder([_LiteralGenerator(content)], '.foo.dart', formatOutput: (s) => s); /// Returns the [String] provided in the constructor, or `null`. class _LiteralGenerator extends Generator { - final String _content; + final String? _content; const _LiteralGenerator([this._content]); @override - String generate(_, __) => _content; + String? generate(_, __) => _content; } class _BadOutputGenerator extends Generator { @@ -671,7 +671,7 @@ class _TestingBuildStep implements BuildStep { @override Future readAsString(AssetId id, {Encoding encoding = utf8}) async => - assets[id]; + assets[id]!; @override void noSuchMethod(_) => throw UnimplementedError(); @@ -688,7 +688,7 @@ class _TestingResolver implements Resolver { Future compilationUnitFor(AssetId assetId, {bool allowSyntaxErrors = false}) async { parsedUnits.add(assetId); - return parseString(content: assets[assetId]).unit; + return parseString(content: assets[assetId]!).unit; } @override @@ -701,7 +701,7 @@ class _TestingResolver implements Resolver { Future libraryFor(AssetId assetId, {bool allowSyntaxErrors = false}) async { resolvedLibs.add(assetId); - return null; + return null as LibraryElement; } @override diff --git a/source_gen/test/constants/utils_test.dart b/source_gen/test/constants/utils_test.dart index d76fd5fb..88ce4f19 100644 --- a/source_gen/test/constants/utils_test.dart +++ b/source_gen/test/constants/utils_test.dart @@ -10,10 +10,11 @@ import 'package:test/test.dart'; void main() { group('assertHasField', () { - LibraryElement testLib; + late LibraryElement testLib; setUpAll(() async { - testLib = await resolveSource(r''' + testLib = await resolveSource( + r''' library test_lib; class A { @@ -27,30 +28,33 @@ void main() { class C { String c; } - ''', (resolver) => resolver.findLibraryByName('test_lib')); + ''', + (resolver) async => (await resolver.findLibraryByName('test_lib'))!, + ); }); test('should not throw when a class contains a field', () { - final $A = testLib.getType('A'); + final $A = testLib.getType('A')!; expect(() => assertHasField($A, 'a'), returnsNormally); }); test('should not throw when a super class contains a field', () { - final $B = testLib.getType('B'); + final $B = testLib.getType('B')!; expect(() => assertHasField($B, 'a'), returnsNormally); }); test('should throw when a class does not contain a field', () { - final $C = testLib.getType('C'); + final $C = testLib.getType('C')!; expect(() => assertHasField($C, 'a'), throwsFormatException); }); }); group('getFieldRecursive', () { - List objects; + late List objects; setUpAll(() async { - final testLib = await resolveSource(r''' + final testLib = await resolveSource( + r''' library test_lib; @A('a-value') @@ -75,21 +79,23 @@ void main() { const C(this.c); } - ''', (resolver) => resolver.findLibraryByName('test_lib')); + ''', + (resolver) async => (await resolver.findLibraryByName('test_lib'))!, + ); objects = testLib - .getType('Example') + .getType('Example')! .metadata - .map((e) => e.computeConstantValue()) + .map((e) => e.computeConstantValue()!) .toList(); }); test('should find a field directly on an object', () { - expect(getFieldRecursive(objects[0], 'a').toStringValue(), 'a-value'); + expect(getFieldRecursive(objects[0], 'a')!.toStringValue(), 'a-value'); }); test('should find a field available on a super', () { - expect(getFieldRecursive(objects[1], 'b').toStringValue(), 'b-value'); - expect(getFieldRecursive(objects[1], 'a').toStringValue(), 'a-value'); + expect(getFieldRecursive(objects[1], 'b')!.toStringValue(), 'b-value'); + expect(getFieldRecursive(objects[1], 'a')!.toStringValue(), 'a-value'); }); test('should return null when a field is not found', () { diff --git a/source_gen/test/constants_test.dart b/source_gen/test/constants_test.dart index b42a7e7e..690251c1 100644 --- a/source_gen/test/constants_test.dart +++ b/source_gen/test/constants_test.dart @@ -9,7 +9,7 @@ import 'package:test/test.dart'; void main() { group('Constant', () { - List constants; + late List constants; setUpAll(() async { final library = await resolveSource(r''' @@ -57,11 +57,11 @@ void main() { class Super extends Example { const Super() : super(aString: 'Super Hello'); } - ''', (resolver) => resolver.findLibraryByName('test_lib')); + ''', (resolver) async => (await resolver.findLibraryByName('test_lib'))!); constants = library - .getType('Example') + .getType('Example')! .metadata - .map((e) => ConstantReader(e.computeConstantValue())) + .map((e) => ConstantReader(e.computeConstantValue()!)) .toList(); }); @@ -126,7 +126,7 @@ void main() { expect(constants[7].isLiteral, isTrue); expect( constants[7].mapValue.map((k, v) => MapEntry( - ConstantReader(k).intValue, ConstantReader(v).stringValue)), + ConstantReader(k!).intValue, ConstantReader(v!).stringValue)), {1: 'A', 2: 'B'}); }); @@ -146,7 +146,7 @@ void main() { test('should read a Type', () { expect(constants[11].isType, isTrue); - expect(constants[11].typeValue.element.name, 'DateTime'); + expect(constants[11].typeValue.element!.name, 'DateTime'); expect(constants[11].isLiteral, isFalse); expect(() => constants[11].literalValue, throwsFormatException); }); @@ -196,10 +196,11 @@ void main() { }); group('Reviable', () { - List constants; + late List constants; setUpAll(() async { - final library = await resolveSource(r''' + final library = await resolveSource( + r''' library test_lib; @Int64Like.ZERO @@ -276,9 +277,11 @@ void main() { } void _privateFunction() {} - ''', (resolver) => resolver.findLibraryByName('test_lib')); + ''', + (resolver) async => (await resolver.findLibraryByName('test_lib'))!, + ); constants = library - .getType('Example') + .getType('Example')! .metadata .map((e) => ConstantReader(e.computeConstantValue())) .toList(); diff --git a/source_gen/test/generator_for_annotation_test.dart b/source_gen/test/generator_for_annotation_test.dart index 8def5cca..dc715382 100644 --- a/source_gen/test/generator_for_annotation_test.dart +++ b/source_gen/test/generator_for_annotation_test.dart @@ -109,12 +109,12 @@ class RepeatingGenerator extends GeneratorForAnnotation { } class LiteralOutput extends GeneratorForAnnotation { - final T value; + final T? value; const LiteralOutput([this.value]); @override - T generateForAnnotatedElement( + T? generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) => null; } diff --git a/source_gen/test/library/find_type_test.dart b/source_gen/test/library/find_type_test.dart index ffbbb99b..3e2a4733 100644 --- a/source_gen/test/library/find_type_test.dart +++ b/source_gen/test/library/find_type_test.dart @@ -29,19 +29,17 @@ enum PartEnum{A,B} '''; void main() { - LibraryReader library; + late LibraryReader library; setUpAll(() async { library = await resolveSources( {'a|source.dart': _source, 'a|part.dart': _partSource}, - (r) async => LibraryReader(await r.findLibraryByName('test_lib')), + (r) async => LibraryReader((await r.findLibraryByName('test_lib'))!), ); }); test('class count', () { expect(library.classes.map((c) => c.name), ['Example', 'PartClass']); - // ignore: deprecated_member_use_from_same_package, deprecated_member_use - expect(library.classElements, orderedEquals(library.classes)); }); test('enum count', () { diff --git a/source_gen/test/library/path_to_url_test.dart b/source_gen/test/library/path_to_url_test.dart index 616c2e38..294bb5ba 100644 --- a/source_gen/test/library/path_to_url_test.dart +++ b/source_gen/test/library/path_to_url_test.dart @@ -9,7 +9,7 @@ import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; void main() { - LibraryReader reader; + late LibraryReader reader; final packageA = Uri.parse('package:a/a.dart'); final packageB = Uri.parse('package:b/b.dart'); diff --git a/source_gen/test/output_helpers_test.dart b/source_gen/test/output_helpers_test.dart index f877e31d..a49839b9 100644 --- a/source_gen/test/output_helpers_test.dart +++ b/source_gen/test/output_helpers_test.dart @@ -42,7 +42,7 @@ void main() { }); } -void _testSimpleValue(String testName, Object value, expected) { +void _testSimpleValue(String testName, Object? value, expected) { _testFunction(testName, value, expected); assert(value is! Future); diff --git a/source_gen/test/span_for_element_test.dart b/source_gen/test/span_for_element_test.dart index f336f7c8..44a38476 100644 --- a/source_gen/test/span_for_element_test.dart +++ b/source_gen/test/span_for_element_test.dart @@ -9,10 +9,11 @@ import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; void main() { - LibraryElement library; + late LibraryElement library; setUpAll(() async { - library = await resolveSource(r''' + library = await resolveSource( + r''' library test_lib; abstract class Example implements List { @@ -24,13 +25,15 @@ abstract class Example implements List { field = value; } } -''', (resolver) => resolver.findLibraryByName('test_lib'), - inputId: AssetId('test_lib', 'lib/test_lib.dart')); +''', + (resolver) async => (await resolver.findLibraryByName('test_lib'))!, + inputId: AssetId('test_lib', 'lib/test_lib.dart'), + ); }); test('should highlight the use of "class Example"', () async { expect( - spanForElement(library.getType('Example')).message('Here it is'), r''' + spanForElement(library.getType('Example')!).message('Here it is'), r''' line 3, column 16 of package:test_lib/test_lib.dart: Here it is ╷ 3 │ abstract class Example implements List { @@ -40,7 +43,7 @@ line 3, column 16 of package:test_lib/test_lib.dart: Here it is test('should correctly highlight getter', () async { expect( - spanForElement(library.getType('Example').getField('getter')) + spanForElement(library.getType('Example')!.getField('getter')!) .message('Here it is'), r''' line 4, column 15 of package:test_lib/test_lib.dart: Here it is @@ -52,7 +55,7 @@ line 4, column 15 of package:test_lib/test_lib.dart: Here it is test('should correctly highlight setter', () async { expect( - spanForElement(library.getType('Example').getField('setter')) + spanForElement(library.getType('Example')!.getField('setter')!) .message('Here it is'), r''' line 5, column 7 of package:test_lib/test_lib.dart: Here it is @@ -64,7 +67,7 @@ line 5, column 7 of package:test_lib/test_lib.dart: Here it is test('should correctly highlight field', () async { expect( - spanForElement(library.getType('Example').getField('field')) + spanForElement(library.getType('Example')!.getField('field')!) .message('Here it is'), r''' line 6, column 7 of package:test_lib/test_lib.dart: Here it is @@ -76,7 +79,7 @@ line 6, column 7 of package:test_lib/test_lib.dart: Here it is test('highlight getter with getter/setter property', () async { expect( - spanForElement(library.getType('Example').getField('fieldProp')) + spanForElement(library.getType('Example')!.getField('fieldProp')!) .message('Here it is'), r''' line 7, column 11 of package:test_lib/test_lib.dart: Here it is diff --git a/source_gen/test/src/comment_generator.dart b/source_gen/test/src/comment_generator.dart index 4aed0504..91401668 100644 --- a/source_gen/test/src/comment_generator.dart +++ b/source_gen/test/src/comment_generator.dart @@ -15,7 +15,7 @@ class CommentGenerator extends Generator { Future generate(LibraryReader library, _) async { final output = []; if (forLibrary) { - var name = library.element.name; + var name = library.element.name!; if (name.isEmpty) { name = library.element.source.uri.pathSegments.last; } diff --git a/source_gen/test/test_files/annotations.dart b/source_gen/test/test_files/annotations.dart index be6dd090..2cb5f0a4 100644 --- a/source_gen/test/test_files/annotations.dart +++ b/source_gen/test/test_files/annotations.dart @@ -19,8 +19,8 @@ class PublicAnnotationClass { final String aString; final List aList; final bool aBool; - final PublicAnnotationClass child1; - final PublicAnnotationClass child2; + final PublicAnnotationClass? child1; + final PublicAnnotationClass? child2; const PublicAnnotationClass() : anInt = 0, diff --git a/source_gen/test/type_checker_test.dart b/source_gen/test/type_checker_test.dart index 20d7c282..b197843b 100644 --- a/source_gen/test/type_checker_test.dart +++ b/source_gen/test/type_checker_test.dart @@ -7,71 +7,73 @@ import 'dart:collection'; import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:build/build.dart'; import 'package:build_test/build_test.dart'; -import 'package:meta/meta.dart'; import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; void main() { // Resolved top-level types from dart:core and dart:collection. - InterfaceType staticUri; - InterfaceType staticMap; - InterfaceType staticHashMap; - InterfaceType staticUnmodifiableListView; - TypeChecker staticIterableChecker; - TypeChecker staticMapChecker; - TypeChecker staticHashMapChecker; + late InterfaceType staticUri; + late InterfaceType staticMap; + late InterfaceType staticHashMap; + late InterfaceType staticUnmodifiableListView; + late TypeChecker staticIterableChecker; + late TypeChecker staticMapChecker; + late TypeChecker staticHashMapChecker; // Resolved top-level types from package:source_gen. - InterfaceType staticGenerator; - InterfaceType staticGeneratorForAnnotation; - TypeChecker staticGeneratorChecker; - TypeChecker staticGeneratorForAnnotationChecker; + late InterfaceType staticGenerator; + late InterfaceType staticGeneratorForAnnotation; + late TypeChecker staticGeneratorChecker; + late TypeChecker staticGeneratorForAnnotationChecker; setUpAll(() async { - LibraryElement core; - LibraryElement collection; - LibraryReader sourceGen; + late LibraryElement core; + late LibraryElement collection; + late LibraryReader sourceGen; await resolveSource(r''' export 'package:source_gen/source_gen.dart'; ''', (resolver) async { - core = await resolver.findLibraryByName('dart.core'); - collection = await resolver.findLibraryByName('dart.collection'); + core = (await resolver.findLibraryByName('dart.core'))!; + collection = (await resolver.findLibraryByName('dart.collection'))!; sourceGen = LibraryReader(await resolver .libraryFor(AssetId('source_gen', 'lib/source_gen.dart'))); }); - final staticIterable = core.getType('Iterable').instantiate( + final staticIterable = core.getType('Iterable')!.instantiate( typeArguments: [core.typeProvider.dynamicType], nullabilitySuffix: NullabilitySuffix.none); staticIterableChecker = TypeChecker.fromStatic(staticIterable); - staticUri = core.getType('Uri').instantiate( + staticUri = core.getType('Uri')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none); - staticMap = core.getType('Map').instantiate(typeArguments: [ + staticMap = core.getType('Map')!.instantiate(typeArguments: [ core.typeProvider.dynamicType, core.typeProvider.dynamicType ], nullabilitySuffix: NullabilitySuffix.none); staticMapChecker = TypeChecker.fromStatic(staticMap); - staticHashMap = collection.getType('HashMap').instantiate(typeArguments: [ - core.typeProvider.dynamicType, - core.typeProvider.dynamicType - ], nullabilitySuffix: NullabilitySuffix.none); + staticHashMap = collection.getType('HashMap')!.instantiate( + typeArguments: [ + core.typeProvider.dynamicType, + core.typeProvider.dynamicType + ], + nullabilitySuffix: NullabilitySuffix.none, + ); staticHashMapChecker = TypeChecker.fromStatic(staticHashMap); staticUnmodifiableListView = collection - .getType('UnmodifiableListView') + .getType('UnmodifiableListView')! .instantiate( typeArguments: [core.typeProvider.dynamicType], nullabilitySuffix: NullabilitySuffix.none); - staticGenerator = sourceGen.findType('Generator').instantiate( + staticGenerator = sourceGen.findType('Generator')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none); staticGeneratorChecker = TypeChecker.fromStatic(staticGenerator); staticGeneratorForAnnotation = sourceGen - .findType('GeneratorForAnnotation') + .findType('GeneratorForAnnotation')! .instantiate( typeArguments: [core.typeProvider.dynamicType], nullabilitySuffix: NullabilitySuffix.none); @@ -81,11 +83,11 @@ void main() { // Run a common set of type comparison checks with various implementations. void commonTests({ - @required TypeChecker Function() checkIterable, - @required TypeChecker Function() checkMap, - @required TypeChecker Function() checkHashMap, - @required TypeChecker Function() checkGenerator, - @required TypeChecker Function() checkGeneratorForAnnotation, + required TypeChecker Function() checkIterable, + required TypeChecker Function() checkMap, + required TypeChecker Function() checkHashMap, + required TypeChecker Function() checkGenerator, + required TypeChecker Function() checkGeneratorForAnnotation, }) { group('(Iterable)', () { test('should be assignable from dart:collection#UnmodifiableListView', @@ -122,7 +124,7 @@ void main() { test('should be assignable from Map', () { // Using Uri.queryParameters to get a Map final stringStringMapType = - staticUri.getGetter('queryParameters').returnType; + staticUri.getGetter('queryParameters')!.returnType; expect(checkMap().isAssignableFromType(stringStringMapType), isTrue); expect(checkMap().isExactlyType(stringStringMapType), isTrue); @@ -205,22 +207,31 @@ void main() { }); test('should fail gracefully when something is not resolvable', () async { - final library = await resolveSource(r''' + final library = await resolveSource( + r''' library _test; @depracated // Intentionally mispelled. class X {} - ''', (resolver) => resolver.findLibraryByName('_test')); - final classX = library.getType('X'); + ''', + (resolver) async => (await resolver.findLibraryByName('_test'))!, + ); + final classX = library.getType('X')!; const $deprecated = TypeChecker.fromRuntime(Deprecated); expect( - () => $deprecated.annotationsOf(classX), - throwsA(const TypeMatcher().having( - (e) => e.toString(), - 'toString', - allOf(contains('Could not resolve annotation for class X'), - contains('@depracated'))))); + () => $deprecated.annotationsOf(classX), + throwsA( + const TypeMatcher().having( + (e) => e.toString(), + 'toString', + allOf( + contains('Could not resolve annotation for class X'), + contains('@depracated'), + ), + ), + ), + ); }); test('should check multiple checkers', () { @@ -232,17 +243,18 @@ void main() { }); group('should find annotations', () { - TypeChecker $A; - TypeChecker $B; - TypeChecker $C; + late TypeChecker $A; + late TypeChecker $B; + late TypeChecker $C; - ClassElement $ExampleOfA; - ClassElement $ExampleOfMultiA; - ClassElement $ExampleOfAPlusB; - ClassElement $ExampleOfBPlusC; + late ClassElement $ExampleOfA; + late ClassElement $ExampleOfMultiA; + late ClassElement $ExampleOfAPlusB; + late ClassElement $ExampleOfBPlusC; setUpAll(() async { - final library = await resolveSource(r''' + final library = await resolveSource( + r''' library _test; @A() @@ -271,59 +283,63 @@ void main() { class C extends B { const C(); } - ''', (resolver) => resolver.findLibraryByName('_test')); - $A = TypeChecker.fromStatic(library.getType('A').instantiate( + ''', + (resolver) async => (await resolver.findLibraryByName('_test'))!, + ); + + $A = TypeChecker.fromStatic(library.getType('A')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none)); - $B = TypeChecker.fromStatic(library.getType('B').instantiate( + $B = TypeChecker.fromStatic(library.getType('B')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none)); - $C = TypeChecker.fromStatic(library.getType('C').instantiate( + $C = TypeChecker.fromStatic(library.getType('C')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none)); - $ExampleOfA = library.getType('ExampleOfA'); - $ExampleOfMultiA = library.getType('ExampleOfMultiA'); - $ExampleOfAPlusB = library.getType('ExampleOfAPlusB'); - $ExampleOfBPlusC = library.getType('ExampleOfBPlusC'); + $ExampleOfA = library.getType('ExampleOfA')!; + $ExampleOfMultiA = library.getType('ExampleOfMultiA')!; + $ExampleOfAPlusB = library.getType('ExampleOfAPlusB')!; + $ExampleOfBPlusC = library.getType('ExampleOfBPlusC')!; }); test('of a single @A', () { expect($A.hasAnnotationOf($ExampleOfA), isTrue); - final aAnnotation = $A.firstAnnotationOf($ExampleOfA); - expect(aAnnotation.type.element.name, 'A'); + final aAnnotation = $A.firstAnnotationOf($ExampleOfA)!; + expect(aAnnotation.type!.element!.name, 'A'); expect($B.annotationsOf($ExampleOfA), isEmpty); expect($C.annotationsOf($ExampleOfA), isEmpty); }); test('of a multiple @A', () { final aAnnotations = $A.annotationsOf($ExampleOfMultiA); - expect(aAnnotations.map((a) => a.type.element.name), ['A', 'A']); + expect(aAnnotations.map((a) => a.type!.element!.name), ['A', 'A']); expect($B.annotationsOf($ExampleOfA), isEmpty); expect($C.annotationsOf($ExampleOfA), isEmpty); }); test('of a single @A + single @B', () { final aAnnotations = $A.annotationsOf($ExampleOfAPlusB); - expect(aAnnotations.map((a) => a.type.element.name), ['A']); + expect(aAnnotations.map((a) => a.type!.element!.name), ['A']); final bAnnotations = $B.annotationsOf($ExampleOfAPlusB); - expect(bAnnotations.map((a) => a.type.element.name), ['B']); + expect(bAnnotations.map((a) => a.type!.element!.name), ['B']); expect($C.annotationsOf($ExampleOfAPlusB), isEmpty); }); test('of a single @B + single @C', () { final cAnnotations = $C.annotationsOf($ExampleOfBPlusC); - expect(cAnnotations.map((a) => a.type.element.name), ['C']); + expect(cAnnotations.map((a) => a.type!.element!.name), ['C']); final bAnnotations = $B.annotationsOf($ExampleOfBPlusC); - expect(bAnnotations.map((a) => a.type.element.name), ['B', 'C']); + expect(bAnnotations.map((a) => a.type!.element!.name), ['B', 'C']); expect($B.hasAnnotationOfExact($ExampleOfBPlusC), isTrue); final bExact = $B.annotationsOfExact($ExampleOfBPlusC); - expect(bExact.map((a) => a.type.element.name), ['B']); + expect(bExact.map((a) => a.type!.element!.name), ['B']); }); }); group('unresolved annotations', () { - TypeChecker $A; - ClassElement $ExampleOfA; + late TypeChecker $A; + late ClassElement $ExampleOfA; setUpAll(() async { - final library = await resolveSource(r''' + final library = await resolveSource( + r''' library _test; // Put the missing annotation first so it throws. @@ -334,10 +350,12 @@ void main() { class A { const A(); } - ''', (resolver) => resolver.findLibraryByName('_test')); - $A = TypeChecker.fromStatic(library.getType('A').instantiate( + ''', + (resolver) async => (await resolver.findLibraryByName('_test'))!, + ); + $A = TypeChecker.fromStatic(library.getType('A')!.instantiate( typeArguments: [], nullabilitySuffix: NullabilitySuffix.none)); - $ExampleOfA = library.getType('ExampleOfA'); + $ExampleOfA = library.getType('ExampleOfA')!; }); test('should throw by default', () { @@ -354,27 +372,27 @@ void main() { test('should not throw if `throwOnUnresolved` == false', () { expect( $A - .firstAnnotationOf($ExampleOfA, throwOnUnresolved: false) - .type - .element + .firstAnnotationOf($ExampleOfA, throwOnUnresolved: false)! + .type! + .element! .name, 'A'); expect( $A .annotationsOf($ExampleOfA, throwOnUnresolved: false) - .map((a) => a.type.element.name), + .map((a) => a.type!.element!.name), ['A']); expect( $A - .firstAnnotationOfExact($ExampleOfA, throwOnUnresolved: false) - .type - .element + .firstAnnotationOfExact($ExampleOfA, throwOnUnresolved: false)! + .type! + .element! .name, 'A'); expect( $A .annotationsOfExact($ExampleOfA, throwOnUnresolved: false) - .map((a) => a.type.element.name), + .map((a) => a.type!.element!.name), ['A']); }); }); diff --git a/source_gen/test/utils_test.dart b/source_gen/test/utils_test.dart index 9d2f59c5..2f2d0e2c 100644 --- a/source_gen/test/utils_test.dart +++ b/source_gen/test/utils_test.dart @@ -10,7 +10,7 @@ import 'package:source_gen/source_gen.dart'; import 'package:test/test.dart'; void main() { - ClassElement example; + late ClassElement example; setUpAll(() async { const source = r''' @@ -28,7 +28,7 @@ void main() { source, (resolver) => resolver .findLibraryByName('example') - .then((e) => e.getType('Example'))); + .then((e) => e!.getType('Example')!)); }); test('should return the name of a class type', () { diff --git a/tool/ci.sh b/tool/ci.sh index de756732..c50db9cd 100755 --- a/tool/ci.sh +++ b/tool/ci.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Created with package:mono_repo v3.4.6 +# Created with package:mono_repo v3.4.7 # Support built in commands on windows out of the box. function pub() {