From c36646aecaff086693c2e12888c7149772fd57df Mon Sep 17 00:00:00 2001 From: Don Date: Wed, 23 Jun 2021 11:05:45 -0700 Subject: [PATCH] Add annotations to libraries --- CHANGELOG.md | 1 + lib/src/emitter.dart | 7 +++++ lib/src/specs/library.dart | 23 ++++++++++++-- lib/src/specs/library.g.dart | 60 +++++++++++++++++++++++++++++++++--- test/specs/library_test.dart | 31 +++++++++++++++++++ 5 files changed, 115 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d8677..cd378e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add support for `Expression.nullChecked` to add a null assertion operator. * Add support for creating `mixin`s. * Add `Expression.nullSafeSpread` for the null aware spread operator `...?`. +* A `Library` can now be annotated. ## 4.0.0 diff --git a/lib/src/emitter.dart b/lib/src/emitter.dart index ca97f27..5922358 100644 --- a/lib/src/emitter.dart +++ b/lib/src/emitter.dart @@ -389,6 +389,13 @@ class DartEmitter extends Object } } + if (spec.name != null) { + spec.annotations.forEach((a) => visitAnnotation(a, output)); + output.write('library ${spec.name!};'); + } else if (spec.annotations.isNotEmpty) { + throw StateError('a library name is required for annotations'); + } + final directives = [...allocator.imports, ...spec.directives]; if (orderDirectives) { diff --git a/lib/src/specs/library.dart b/lib/src/specs/library.dart index d4ee597..c007c49 100644 --- a/lib/src/specs/library.dart +++ b/lib/src/specs/library.dart @@ -7,19 +7,31 @@ import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; +import '../mixins/annotations.dart'; import '../visitors.dart'; import 'directive.dart'; +import 'expression.dart'; part 'library.g.dart'; @immutable -abstract class Library implements Built, Spec { +abstract class Library + with HasAnnotations + implements Built, Spec { factory Library([void Function(LibraryBuilder) updates]) = _$Library; Library._(); + @override + BuiltList get annotations; + BuiltList get directives; BuiltList get body; + /// Name of the library. + /// + /// May be `null` when no [annotations] are specified. + String? get name; + @override R accept( SpecVisitor visitor, [ @@ -28,10 +40,17 @@ abstract class Library implements Built, Spec { visitor.visitLibrary(this, context); } -abstract class LibraryBuilder implements Builder { +abstract class LibraryBuilder + with HasAnnotationsBuilder + implements Builder { factory LibraryBuilder() = _$LibraryBuilder; LibraryBuilder._(); + @override + ListBuilder annotations = ListBuilder(); + ListBuilder body = ListBuilder(); ListBuilder directives = ListBuilder(); + + String? name; } diff --git a/lib/src/specs/library.g.dart b/lib/src/specs/library.g.dart index b9178ec..298779d 100644 --- a/lib/src/specs/library.g.dart +++ b/lib/src/specs/library.g.dart @@ -7,15 +7,26 @@ part of 'library.dart'; // ************************************************************************** class _$Library extends Library { + @override + final BuiltList annotations; @override final BuiltList directives; @override final BuiltList body; + @override + final String? name; factory _$Library([void Function(LibraryBuilder)? updates]) => (new LibraryBuilder()..update(updates)).build() as _$Library; - _$Library._({required this.directives, required this.body}) : super._() { + _$Library._( + {required this.annotations, + required this.directives, + required this.body, + this.name}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + annotations, 'Library', 'annotations'); BuiltValueNullFieldError.checkNotNull(directives, 'Library', 'directives'); BuiltValueNullFieldError.checkNotNull(body, 'Library', 'body'); } @@ -31,20 +42,27 @@ class _$Library extends Library { bool operator ==(Object other) { if (identical(other, this)) return true; return other is Library && + annotations == other.annotations && directives == other.directives && - body == other.body; + body == other.body && + name == other.name; } @override int get hashCode { - return $jf($jc($jc(0, directives.hashCode), body.hashCode)); + return $jf($jc( + $jc($jc($jc(0, annotations.hashCode), directives.hashCode), + body.hashCode), + name.hashCode)); } @override String toString() { return (newBuiltValueToStringHelper('Library') + ..add('annotations', annotations) ..add('directives', directives) - ..add('body', body)) + ..add('body', body) + ..add('name', name)) .toString(); } } @@ -52,6 +70,18 @@ class _$Library extends Library { class _$LibraryBuilder extends LibraryBuilder { _$Library? _$v; + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + @override ListBuilder get directives { _$this; @@ -76,13 +106,27 @@ class _$LibraryBuilder extends LibraryBuilder { super.body = body; } + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + _$LibraryBuilder() : super._(); LibraryBuilder get _$this { final $v = _$v; if ($v != null) { + super.annotations = $v.annotations.toBuilder(); super.directives = $v.directives.toBuilder(); super.body = $v.body.toBuilder(); + super.name = $v.name; _$v = null; } return this; @@ -104,10 +148,16 @@ class _$LibraryBuilder extends LibraryBuilder { _$Library _$result; try { _$result = _$v ?? - new _$Library._(directives: directives.build(), body: body.build()); + new _$Library._( + annotations: annotations.build(), + directives: directives.build(), + body: body.build(), + name: name); } catch (_) { late String _$failedField; try { + _$failedField = 'annotations'; + annotations.build(); _$failedField = 'directives'; directives.build(); _$failedField = 'body'; diff --git a/test/specs/library_test.dart b/test/specs/library_test.dart index 63b0807..e7391a9 100644 --- a/test/specs/library_test.dart +++ b/test/specs/library_test.dart @@ -137,5 +137,36 @@ void main() { ''', DartEmitter()), ); }); + + test('should emit a source file with annotations', () { + expect( + Library( + (b) => b + ..name = 'js_interop' + ..annotations.add( + refer('JS', 'package:js/js.dart').call([]), + ), + ), + equalsDart(r''' + @JS() + library js_interop; + import 'package:js/js.dart'; + ''', DartEmitter(allocator: Allocator())), + ); + }); + + test('should error on unnamed library with annotations', () { + expect( + () { + Library( + (b) => b + ..annotations.add( + refer('JS', 'package:js/js.dart').call([]), + ), + ).accept(DartEmitter()); + }, + throwsStateError, + ); + }); }); }