Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 1.0.0-beta+4

- Renamed `PartBuilder` to `PartOfBuilder`.
- Added a new class, `PartBuilder`, to represent `part '...dart'` directives.
- Added the `HasAnnotations` interface to all library/part/directive builders.
- Added `asFactory` and `asConst` to `ConstructorBuilder`.
- Added `ConstructorBuilder.redirectTo` for a redirecting factory constructor.
- Added a `name` getter to `ReferenceBuilder`.
- Supplying an empty constructor name (`''`) is equivalent to `null` (default).
- Automatically encodes string literals with multiple lines as `'''`.

## 1.0.0-beta+3

- Added support for `genericTypes` parameter for `ExpressionBuilder#invoke`:
Expand Down
7 changes: 6 additions & 1 deletion lib/code_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ export 'src/builders/expression.dart'
export 'src/builders/field.dart'
show varConst, varField, varFinal, FieldBuilder;
export 'src/builders/file.dart'
show ExportBuilder, ImportBuilder, LibraryBuilder, PartBuilder;
show
ExportBuilder,
ImportBuilder,
LibraryBuilder,
PartBuilder,
PartOfBuilder;
export 'src/builders/method.dart'
show
constructor,
Expand Down
80 changes: 55 additions & 25 deletions lib/src/builders/file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:code_builder/src/builders/annotation.dart';
import 'package:code_builder/src/builders/shared.dart';
import 'package:code_builder/src/builders/statement.dart';
import 'package:code_builder/src/tokens.dart';

/// Builds a file of Dart source code.
///
/// See [LibraryBuilder] and [PartBuilder] for concrete implementations.
/// See [LibraryBuilder] and [PartOfBuilder] for concrete implementations.
abstract class FileBuilder implements AstBuilder<CompilationUnit> {
final List<AstBuilder> _members = <AstBuilder>[];

Expand All @@ -28,8 +29,9 @@ abstract class FileBuilder implements AstBuilder<CompilationUnit> {
}

/// Builds a standalone file (library) of Dart source code.
class LibraryBuilder extends FileBuilder {
class LibraryBuilder extends FileBuilder with HasAnnotationsMixin {
final List<AstBuilder<Directive>> _directives = <AstBuilder<Directive>>[];
final String _name;
final Scope _scope;

/// Creates a new standalone Dart library, optionally with [name].
Expand All @@ -43,11 +45,7 @@ class LibraryBuilder extends FileBuilder {
return new LibraryBuilder._(name, scope ?? new Scope());
}

LibraryBuilder._(String name, this._scope) : super._() {
if (name != null) {
_directives.add(new _LibraryDirectiveBuilder(name));
}
}
LibraryBuilder._(this._name, this._scope) : super._();

/// Adds a file [directive].
void addDirective(AstBuilder<Directive> directive) {
Expand All @@ -60,14 +58,18 @@ class LibraryBuilder extends FileBuilder {
}

@override
CompilationUnit buildAst([_]) {
CompilationUnit buildAst([Scope scope]) {
var members = _members.map((m) {
if (m is TopLevelMixin) {
return (m as TopLevelMixin).buildTopLevelAst(_scope);
}
return m.buildAst(_scope);
}).toList();
var directives = <Directive>[]
var directives = <Directive>[];
if (_name != null) {
directives.add(new _LibraryDirectiveBuilder(_name, this).buildAst(scope));
}
directives
..addAll(_scope.toImports().map((d) => d.buildAst()))
..addAll(_directives.map((d) => d.buildAst()));
return astFactory.compilationUnit(
Expand All @@ -81,28 +83,30 @@ class LibraryBuilder extends FileBuilder {
}

/// Lazily builds a partial file (part of) Dart source code.
class PartBuilder extends FileBuilder {
final String _name;
class PartOfBuilder extends FileBuilder with HasAnnotationsMixin {
final String _uri;
final Scope _scope;

/// Creates a partial Dart file.
factory PartBuilder(String name) = PartBuilder._;
factory PartOfBuilder(String uri, [Scope scope]) = PartOfBuilder._;

PartBuilder._(this._name) : super._();
PartOfBuilder._(this._uri, [this._scope]) : super._();

@override
CompilationUnit buildAst([_]) {
CompilationUnit buildAst([Scope scope]) {
scope ??= _scope;
return astFactory.compilationUnit(
null,
null,
[
astFactory.partOfDirective(
null,
null,
buildAnnotations(scope),
$part,
$of,
null,
astFactory.libraryIdentifier([
astFactory.simpleIdentifier(stringToken(_name)),
astFactory.simpleIdentifier(stringToken("'$_uri'")),
]),
$semicolon,
)
Expand All @@ -119,15 +123,16 @@ class PartBuilder extends FileBuilder {
}

class _LibraryDirectiveBuilder implements AstBuilder<LibraryDirective> {
final LibraryBuilder _library;
final String _name;

_LibraryDirectiveBuilder(this._name);
_LibraryDirectiveBuilder(this._name, this._library);

@override
LibraryDirective buildAst([_]) {
LibraryDirective buildAst([Scope scope]) {
return astFactory.libraryDirective(
null,
null,
_library.buildAnnotations(scope),
$library,
astFactory.libraryIdentifier([
astFactory.simpleIdentifier(
Expand All @@ -139,8 +144,31 @@ class _LibraryDirectiveBuilder implements AstBuilder<LibraryDirective> {
}
}

/// Lazily builds a [PartDirective] AST when built.
class PartBuilder extends Object
with HasAnnotationsMixin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[optional] could be class PartBuilder extends HasAnnotationsMixin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. I like keeping it like this to ensure it stays mixin compatible.

implements AstBuilder<PartDirective> {
final String _uri;

factory PartBuilder(String uri) = PartBuilder._;
PartBuilder._(this._uri);

@override
PartDirective buildAst([Scope scope]) {
return astFactory.partDirective(
null,
buildAnnotations(scope),
$part,
astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri),
$semicolon,
);
}
}

/// Lazily builds an [ImportDirective] AST when built.
class ImportBuilder implements AstBuilder<ImportDirective> {
class ImportBuilder extends Object
with HasAnnotationsMixin
implements AstBuilder<ImportDirective> {
final String _prefix;
final String _uri;
final bool _deferred;
Expand Down Expand Up @@ -171,7 +199,7 @@ class ImportBuilder implements AstBuilder<ImportDirective> {
}

@override
ImportDirective buildAst([_]) {
ImportDirective buildAst([Scope scope]) {
var combinators = <Combinator>[];
if (_show.isNotEmpty) {
combinators.add(
Expand All @@ -191,7 +219,7 @@ class ImportBuilder implements AstBuilder<ImportDirective> {
}
return astFactory.importDirective(
null,
null,
buildAnnotations(scope),
null,
astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri),
null,
Expand All @@ -205,7 +233,9 @@ class ImportBuilder implements AstBuilder<ImportDirective> {
}

/// Lazily builds an [ExportDirective] AST when built.
class ExportBuilder implements AstBuilder<ExportDirective> {
class ExportBuilder extends Object
with HasAnnotationsMixin
implements AstBuilder<ExportDirective> {
final String _uri;

final Set<String> _show = new Set<String>();
Expand All @@ -232,7 +262,7 @@ class ExportBuilder implements AstBuilder<ExportDirective> {
}

@override
ExportDirective buildAst([_]) {
ExportDirective buildAst([Scope scope]) {
var combinators = <Combinator>[];
if (_show.isNotEmpty) {
combinators.add(
Expand All @@ -252,7 +282,7 @@ class ExportBuilder implements AstBuilder<ExportDirective> {
}
return astFactory.exportDirective(
null,
null,
buildAnnotations(scope),
null,
astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri),
null,
Expand Down
89 changes: 86 additions & 3 deletions lib/src/builders/method.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ typedef void _AddParameter(ConstructorBuilder constructor);
abstract class ConstructorBuilder
implements
AstBuilder<ConstructorDeclaration>,
HasAnnotations,
HasParameters,
HasStatements,
ValidClassMember {
Expand All @@ -193,8 +194,18 @@ abstract class ConstructorBuilder
String name,
String superName,
List<ExpressionBuilder> invokeSuper,
bool asConst,
bool asFactory,
}) = _NormalConstructorBuilder;

/// Create a new [ConstructorBuilder] that redirects to another constructor.
factory ConstructorBuilder.redirectTo(
String name,
TypeBuilder redirectToClass, {
String constructor,
bool asConst,
}) = _RedirectingConstructorBuilder;

/// Adds a field initializer to this constructor.
void addInitializer(
String fieldName, {
Expand Down Expand Up @@ -541,10 +552,78 @@ class _NamedParameterWrapper
AstNode buildAst([_]) => throw new UnsupportedError('Use within method');
}

class _RedirectingConstructorBuilder extends Object
with HasAnnotationsMixin, HasParametersMixin
implements ConstructorBuilder {
final String name;
final TypeBuilder redirectToClass;
final bool asConst;
final String constructor;

_RedirectingConstructorBuilder(
this.name,
this.redirectToClass, {
this.asConst: false,
this.constructor,
});

@override
void addInitializer(
String fieldName, {
ExpressionBuilder toExpression,
String toParameter,
}) {
throw new UnsupportedError('Not valid for redirect constructors');
}

@override
void addStatement(StatementBuilder statement) {
throw new UnsupportedError('Not valid for redirect constructors');
}

@override
void addStatements(Iterable<StatementBuilder> statements) {
throw new UnsupportedError('Not valid for redirect constructors');
}

@override
ConstructorDeclaration buildAst([_]) {
throw new UnsupportedError('Can only be built as part of a class.');
}

@override
ConstructorDeclaration buildConstructor(
TypeBuilder returnType, [
Scope scope,
]) {
return astFactory.constructorDeclaration(
null,
buildAnnotations(scope),
null,
asConst ? $const : null,
$factory,
returnType.buildType(scope).name,
name != null ? $period : null,
name != null ? stringIdentifier(name) : null,
buildParameterList(scope),
null,
null,
astFactory.constructorName(
redirectToClass.buildType(scope),
constructor != null ? $period : null,
constructor != null ? stringIdentifier(constructor) : null,
),
astFactory.emptyFunctionBody($semicolon),
);
}
}

class _NormalConstructorBuilder extends Object
with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin
implements ConstructorBuilder {
final _initializers = <String, ExpressionBuilder>{};
final bool _asFactory;
final bool _asConst;
final String _name;
final String _superName;
final List<ExpressionBuilder> _superInvocation;
Expand All @@ -553,10 +632,14 @@ class _NormalConstructorBuilder extends Object
List<ExpressionBuilder> invokeSuper,
String name,
String superName,
bool asConst: false,
bool asFactory: false,
})
: _name = name,
_superInvocation = invokeSuper,
_superName = superName;
_superName = superName,
_asConst = asConst,
_asFactory = asFactory;

@override
void addInitializer(
Expand Down Expand Up @@ -611,8 +694,8 @@ class _NormalConstructorBuilder extends Object
null,
buildAnnotations(scope),
null,
null,
null,
_asConst ? $const : null,
_asFactory ? $factory : null,
returnType.buildType(scope).name,
_name != null ? $period : null,
_name != null ? stringIdentifier(_name) : null,
Expand Down
Loading