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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@

This should help cover any cases not covered with builders today.

- Allow referring to a `ClassBuilder` and `TypeBuilder` as an expression
- Add support for accessing the index `[]` operator on an expression

### BREAKING CHANGES

- Changed `ExpressionBuilder.asAssign` to always take an `ExpressionBuilder` as
target and removed the `value` property. Most changes are pretty simple, and
involve just using `reference(...)`. For example:

```dart
literal(true).asAssign(reference('flag'))
```

... emits `flag = true`.

## 1.0.0-beta

- Add support for `async`, `sync`, `sync*` functions
Expand Down
13 changes: 12 additions & 1 deletion lib/src/builders/class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:code_builder/dart/core.dart';
import 'package:code_builder/src/builders/annotation.dart';
import 'package:code_builder/src/builders/expression.dart';
import 'package:code_builder/src/builders/field.dart';
import 'package:code_builder/src/builders/file.dart';
import 'package:code_builder/src/builders/method.dart';
import 'package:code_builder/src/builders/reference.dart';
import 'package:code_builder/src/builders/shared.dart';
import 'package:code_builder/src/builders/statement.dart';
import 'package:code_builder/src/builders/type.dart';
import 'package:code_builder/src/tokens.dart';

Expand Down Expand Up @@ -133,7 +136,7 @@ abstract class ClassBuilder
abstract class ValidClassMember implements AstBuilder {}

class _ClassBuilderImpl extends Object
with AbstractTypeBuilderMixin, HasAnnotationsMixin
with AbstractExpressionMixin, AbstractTypeBuilderMixin, HasAnnotationsMixin
implements ClassBuilder {
final _constructors = <ConstructorBuilder>[];
final _fields = <FieldBuilder, bool>{};
Expand Down Expand Up @@ -265,6 +268,14 @@ class _ClassBuilderImpl extends Object
ImportBuilder toImportBuilder({bool deferred: false, String prefix}) {
throw new UnsupportedError('Not supported for ClassBuilder');
}

@override
Expression buildExpression([Scope scope]) {
return reference(_name).buildExpression(scope);
}

@override
CompilationUnitMember buildTopLevelAst([Scope scope]) => buildClass(scope);
}

class _TypeNameWrapper implements ValidClassMember {
Expand Down
21 changes: 13 additions & 8 deletions lib/src/builders/expression.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ part 'expression/assert.dart';
part 'expression/assign.dart';
part 'expression/await.dart';
part 'expression/cascade.dart';
part 'expression/index.dart';
part 'expression/invocation.dart';
part 'expression/negate.dart';
part 'expression/operators.dart';
Expand Down Expand Up @@ -146,6 +147,11 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder {
);
}

@override
ExpressionBuilder operator [](ExpressionBuilder index) {
return new _IndexExpression(this, index);
}

@override
ExpressionBuilder and(ExpressionBuilder other) {
return new _AsBinaryExpression(
Expand All @@ -160,11 +166,10 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder {

@override
StatementBuilder asAssign(
String variable, {
ExpressionBuilder target,
ExpressionBuilder target, {
bool nullAware: false,
}) =>
new _AsAssign(this, variable, nullAware, target);
new _AsAssign(this, nullAware, target);

@override
ExpressionBuilder asAwait() => new _AsAwait(this);
Expand Down Expand Up @@ -320,18 +325,18 @@ abstract class ExpressionBuilder
/// Returns as an [ExpressionBuilder] `>` by [other].
ExpressionBuilder operator >(ExpressionBuilder other);

/// Returns as an [ExpressionBuilder] reading the `[]` property with [index].
ExpressionBuilder operator [](ExpressionBuilder index);

/// Returns as an [ExpressionBuilder] `&&` [other].
ExpressionBuilder and(ExpressionBuilder other);

/// Return as a [StatementBuilder] that `assert`s this expression.
StatementBuilder asAssert();

/// Returns as a [StatementBuilder] that assigns to an existing [variable].
///
/// If [target] is specified, determined to be `{target}.{variable}`.
/// Returns as a [StatementBuilder] that assigns to [target].
StatementBuilder asAssign(
String variable, {
ExpressionBuilder target,
ExpressionBuilder target, {
bool nullAware,
});

Expand Down
7 changes: 2 additions & 5 deletions lib/src/builders/expression/assign.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@
part of code_builder.src.builders.expression;

class _AsAssign extends AbstractExpressionMixin with TopLevelMixin {
final String _name;
final bool _nullAware;
final ExpressionBuilder _value;
final ExpressionBuilder _target;

_AsAssign(this._value, this._name, this._nullAware, this._target);
_AsAssign(this._value, this._nullAware, this._target);

@override
AstNode buildAst([Scope scope]) => buildExpression(scope);

@override
Expression buildExpression([Scope scope]) {
return astFactory.assignmentExpression(
_target != null
? _target.property(_name).buildExpression(scope)
: stringIdentifier(_name),
_target.buildExpression(scope),
_nullAware ? $nullAwareEquals : $equals,
_value.buildExpression(scope),
);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/builders/expression/await.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class _AsAwait extends AbstractExpressionMixin with TopLevelMixin {

@override
Expression buildExpression([Scope scope]) {
return new AwaitExpression(
return astFactory.awaitExpression(
$await,
_expression.buildExpression(scope),
);
Expand Down
25 changes: 25 additions & 0 deletions lib/src/builders/expression/index.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of code_builder.src.builders.expression;

class _IndexExpression extends AbstractExpressionMixin with TopLevelMixin {
final ExpressionBuilder _target;
final ExpressionBuilder _index;

_IndexExpression(this._target, this._index);

@override
AstNode buildAst([Scope scope]) => buildExpression(scope);

@override
Expression buildExpression([Scope scope]) {
return astFactory.indexExpressionForTarget(
_target.buildExpression(scope),
$openBracket,
_index.buildExpression(scope),
$closeBracket,
);
}
}
2 changes: 1 addition & 1 deletion lib/src/builders/expression/yield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class _AsYield extends TopLevelMixin implements StatementBuilder {

@override
Statement buildStatement([Scope scope]) {
return new YieldStatement(
return astFactory.yieldStatement(
$yield,
_isStar ? $star : null,
_expression.buildExpression(scope),
Expand Down
85 changes: 52 additions & 33 deletions lib/src/builders/statement/switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,35 @@ import 'package:code_builder/src/builders/statement.dart';
import 'package:code_builder/src/tokens.dart';

/// Short-hand syntax for `new SwitchCaseBuilder(...)`.
SwitchCaseBuilder switchCase(ExpressionBuilder condition,
[Iterable<StatementBuilder> statements = const []]) =>
SwitchCaseBuilder switchCase(
ExpressionBuilder condition, [
Iterable<StatementBuilder> statements = const [],
]) =>
new SwitchCaseBuilder(condition)..addStatements(statements ?? []);

/// Short-hand syntax for `new SwitchDefaultCaseBuilder(...)`.
SwitchDefaultCaseBuilder switchDefault(
[Iterable<StatementBuilder> statements = const []]) =>
SwitchDefaultCaseBuilder switchDefault([
Iterable<StatementBuilder> statements = const [],
]) =>
new SwitchDefaultCaseBuilder()..addStatements(statements ?? []);

/// Short-hand syntax for `new SwitchStatementBuilder(...)`.
SwitchStatementBuilder switchStatement(ExpressionBuilder expression,
{Iterable<SwitchCaseBuilder> cases: const [],
SwitchDefaultCaseBuilder defaultCase}) =>
SwitchStatementBuilder switchStatement(
ExpressionBuilder expression, {
Iterable<SwitchCaseBuilder> cases: const [],
SwitchDefaultCaseBuilder defaultCase,
}) =>
new SwitchStatementBuilder(expression)
..setDefaultCase(defaultCase)
..addCases(cases ?? []);

/// Represents an [ExpressionBuilder] and a series of [SwitchCaseBuilder]s as a switch statement AST.
/// Represents an [ExpressionBuilder] switches as an AST.
abstract class SwitchStatementBuilder implements StatementBuilder {
/// Creates a new [SwitchStatementBuilder].
factory SwitchStatementBuilder(ExpressionBuilder expression,
[Iterable<ValidSwitchMember> members = const []]) =>
factory SwitchStatementBuilder(
ExpressionBuilder expression, [
Iterable<ValidSwitchMember> members = const [],
]) =>
new _SwitchStatementBuilder(expression, members);

/// Adds a [switchCase] to the builder.
Expand All @@ -47,16 +54,15 @@ abstract class SwitchStatementBuilder implements StatementBuilder {
void setDefaultCase(SwitchDefaultCaseBuilder defaultCase);
}

/// A marker interface for an AST that could be added to [SwitchStatementBuilder].
/// A marker interface for an AST usable within a [SwitchStatementBuilder].
///
/// This can be either a [SwitchCaseBuilder] or a [SwitchDefaultCaseBuilder].
abstract class ValidSwitchMember {}

/// Represents an [ExpressionBuilder] and a series of [Statement]s as a switch case AST.
/// Represents an [ExpressionBuilder] and statements as a switch case AST.
abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember {
/// Creates a new [SwitchCaseBuilder].
factory SwitchCaseBuilder(ExpressionBuilder condition) =>
new _SwitchCaseBuilder(condition);
factory SwitchCaseBuilder(ExpressionBuilder condition) = _SwitchCaseBuilder;

/// Returns an [SwitchMember] AST representing the builder.
SwitchMember buildSwitchMember([Scope scope]);
Expand All @@ -65,7 +71,7 @@ abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember {
/// Represents a series of [Statement]s as a default switch case AST.
abstract class SwitchDefaultCaseBuilder
implements HasStatements, ValidSwitchMember {
factory SwitchDefaultCaseBuilder() => new _SwitchDefaultCaseBuilder();
factory SwitchDefaultCaseBuilder() = _SwitchDefaultCaseBuilder;

/// Returns an [SwitchMember] AST representing the builder.
SwitchMember buildSwitchMember([Scope scope]);
Expand All @@ -78,12 +84,16 @@ class _SwitchStatementBuilder extends Object
final List<SwitchCaseBuilder> _cases = [];
SwitchDefaultCaseBuilder _defaultCase;

_SwitchStatementBuilder(this._expression,
[Iterable<ValidSwitchMember> members = const []]) {
_SwitchStatementBuilder(
this._expression, [
Iterable<ValidSwitchMember> members = const [],
]) {
for (final member in members) {
if (member is SwitchDefaultCaseBuilder)
if (member is SwitchDefaultCaseBuilder) {
_defaultCase = member;
else if (member is SwitchCaseBuilder) _cases.add(member);
} else if (member is SwitchCaseBuilder) {
_cases.add(member);
}
}
}

Expand All @@ -105,18 +115,18 @@ class _SwitchStatementBuilder extends Object
@override
SwitchStatement buildSwitchStatement([Scope scope]) {
var members = _cases.map((c) => c.buildSwitchMember(scope)).toList();

if (_defaultCase != null)
if (_defaultCase != null) {
members.add(_defaultCase.buildSwitchMember(scope));

}
return astFactory.switchStatement(
$switch,
$openBracket,
_expression.buildExpression(),
$closeParen,
$openBracket,
members,
$closeBracket);
$switch,
$openBracket,
_expression.buildExpression(),
$closeParen,
$openBracket,
members,
$closeBracket,
);
}

@override
Expand All @@ -134,8 +144,13 @@ class _SwitchCaseBuilder extends Object
AstNode buildAst([Scope scope]) => buildSwitchMember(scope);

@override
SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase(null,
$case, _condition.buildExpression(), $colon, buildStatements(scope));
SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase(
null,
$case,
_condition.buildExpression(),
$colon,
buildStatements(scope),
);
}

class _SwitchDefaultCaseBuilder extends Object
Expand All @@ -145,6 +160,10 @@ class _SwitchDefaultCaseBuilder extends Object
AstNode buildAst([Scope scope]) => buildSwitchMember(scope);

@override
SwitchMember buildSwitchMember([Scope scope]) =>
astFactory.switchDefault(null, $default, $colon, buildStatements());
SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchDefault(
null,
$default,
$colon,
buildStatements(),
);
}
16 changes: 14 additions & 2 deletions lib/src/builders/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,12 @@ abstract class AbstractTypeBuilderMixin {

/// Lazily builds an [TypeName] AST when [buildType] is invoked.
class TypeBuilder extends Object
with AbstractTypeBuilderMixin
implements AstBuilder, ValidMethodMember, ValidParameterMember {
with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin
implements
AstBuilder,
ExpressionBuilder,
ValidMethodMember,
ValidParameterMember {
final List<TypeBuilder> _generics;
final String _importFrom;
final String _name;
Expand Down Expand Up @@ -150,4 +154,12 @@ class TypeBuilder extends Object
prefix: prefix,
)..show(_name);
}

@override
Expression buildExpression([Scope scope]) {
if (_generics.isNotEmpty) {
throw new StateError('Cannot refer to a type with generic parameters');
}
return reference(_name, _importFrom).buildExpression(scope);
}
}
Loading