Skip to content

Commit

Permalink
Add annotations to libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
donny-dont committed Jun 23, 2021
1 parent 1426c2d commit c5bba7e
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
* Add `Expression.spread` for the spread operator `...`.
* Add support 'late' field modifier.
* Add support for `Expression.nullChecked` to add a null assertion operator.
* A `Library` can now be annotated.

## 4.0.0

Expand Down
7 changes: 7 additions & 0 deletions lib/src/emitter.dart
Expand Up @@ -354,6 +354,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 = <Directive>[...allocator.imports, ...spec.directives];

if (orderDirectives) {
Expand Down
23 changes: 21 additions & 2 deletions lib/src/specs/library.dart
Expand Up @@ -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<Library, LibraryBuilder>, Spec {
abstract class Library
with HasAnnotations
implements Built<Library, LibraryBuilder>, Spec {
factory Library([void Function(LibraryBuilder) updates]) = _$Library;
Library._();

@override
BuiltList<Expression> get annotations;

BuiltList<Directive> get directives;
BuiltList<Spec> get body;

/// Name of the library.
///
/// May be `null` when no [annotations] are specified.
String? get name;

@override
R accept<R>(
SpecVisitor<R> visitor, [
Expand All @@ -28,10 +40,17 @@ abstract class Library implements Built<Library, LibraryBuilder>, Spec {
visitor.visitLibrary(this, context);
}

abstract class LibraryBuilder implements Builder<Library, LibraryBuilder> {
abstract class LibraryBuilder
with HasAnnotationsBuilder
implements Builder<Library, LibraryBuilder> {
factory LibraryBuilder() = _$LibraryBuilder;
LibraryBuilder._();

@override
ListBuilder<Expression> annotations = ListBuilder<Expression>();

ListBuilder<Spec> body = ListBuilder<Spec>();
ListBuilder<Directive> directives = ListBuilder<Directive>();

String? name;
}
60 changes: 55 additions & 5 deletions lib/src/specs/library.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions test/specs/library_test.dart
Expand Up @@ -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,
);
});
});
}

0 comments on commit c5bba7e

Please sign in to comment.