Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.

Commit 3aaf168

Browse files
authored
Add support for generic types in methods and as cast (#70)
* Add support for generic types and as cast * Update CHANGELOG and pubspec. * Rename name: to constructor:
1 parent 74667ee commit 3aaf168

File tree

11 files changed

+231
-74
lines changed

11 files changed

+231
-74
lines changed

CHANGELOG.md

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,67 @@
1+
## 1.0.0-beta+3
2+
3+
- Added support for `genericTypes` parameter for `ExpressionBuilder#invoke`:
4+
5+
```dart
6+
expect(
7+
explicitThis.invoke('doThing', [literal(true)], genericTypes: [
8+
lib$core.bool,
9+
]),
10+
equalsSource(r'''
11+
this.doThing<bool>(true)
12+
'''),
13+
);
14+
```
15+
16+
- Added a `castAs` method to `ExpressionBuilder`:
17+
18+
```dart
19+
expect(
20+
literal(1.0).castAs(lib$core.num),
21+
equalsSource(r'''
22+
1.0 as num
23+
'''),
24+
);
25+
```
26+
27+
### BREAKING CHANGES
28+
29+
- Removed `namedNewInstance` and `namedConstInstance`, replaced with `constructor: `:
30+
31+
```dart
32+
expect(
33+
reference('Foo').newInstance([], constructor: 'other'),
34+
equalsSource(r'''
35+
new Foo.other()
36+
'''),
37+
);
38+
```
39+
40+
- Renamed `named` parameter to `namedArguments`:
41+
42+
```dart
43+
expect(
44+
reference('doThing').call(
45+
[literal(true)],
46+
namedArguments: {
47+
'otherFlag': literal(false),
48+
},
49+
),
50+
equalsSource(r'''
51+
doThing(true, otherFlag: false)
52+
'''),
53+
);
54+
```
55+
156
## 1.0.0-beta+2
257

3-
- BREAKING CHANGE: `MethodModifier.async`, `MethodModifier.asyncStar` and
4-
`MethodModifier.syncStar` are now `MethodModifier.asAsync`,
5-
`MethodModifier.asAsyncStar` and `MethodModifier.asSyncStar`
58+
### BREAKING CHANGES
59+
60+
Avoid creating symbols that can collide with the Dart language:
61+
62+
- `MethodModifier.async` -> `MethodModifier.asAsync`
63+
- `MethodModifier.asyncStar` -> `MethodModifier.asAsyncStar`
64+
- `MethodModifier.syncStar` -> `MethodModifier.asSyncStar`
665

766
## 1.0.0-beta+1
867

lib/dart/core.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class DartCore {
5353
/// References [dart_core.int].
5454
final ReferenceBuilder int = _ref('int');
5555

56+
/// References [dart_core.num].
57+
final ReferenceBuilder num = _ref('num');
58+
5659
/// References [dart_core.AbstractClassInstantiationError].
5760
final ReferenceBuilder AbstractClassInstantiationError =
5861
_ref('AbstractClassInstantiationError');

lib/src/builders/expression.dart

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ part 'expression/assert.dart';
2323
part 'expression/assign.dart';
2424
part 'expression/await.dart';
2525
part 'expression/cascade.dart';
26+
part 'expression/cast.dart';
2627
part 'expression/index.dart';
2728
part 'expression/invocation.dart';
2829
part 'expression/negate.dart';
@@ -216,15 +217,18 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder {
216217

217218
@override
218219
InvocationBuilder call(
219-
Iterable<ExpressionBuilder> positionalArguments, [
220-
Map<String, ExpressionBuilder> namedArguments = const {},
221-
]) {
220+
Iterable<ExpressionBuilder> positionalArguments, {
221+
Map<String, ExpressionBuilder> namedArguments: const {},
222+
}) {
222223
final invocation = new InvocationBuilder._(this);
223224
positionalArguments.forEach(invocation.addPositionalArgument);
224225
namedArguments.forEach(invocation.addNamedArgument);
225226
return invocation;
226227
}
227228

229+
@override
230+
ExpressionBuilder castAs(TypeBuilder type) => new _AsCast(this, type);
231+
228232
@override
229233
ExpressionBuilder cascade(
230234
Iterable<ExpressionBuilder> create(ExpressionBuilder self),
@@ -261,10 +265,15 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder {
261265
@override
262266
InvocationBuilder invoke(
263267
String method,
264-
Iterable<ExpressionBuilder> positionalArguments, [
265-
Map<String, ExpressionBuilder> namedArguments = const {},
266-
]) {
267-
final invocation = new InvocationBuilder._on(this, method);
268+
Iterable<ExpressionBuilder> positionalArguments, {
269+
Iterable<TypeBuilder> genericTypes: const [],
270+
Map<String, ExpressionBuilder> namedArguments: const {},
271+
}) {
272+
final invocation = new InvocationBuilder._on(
273+
this,
274+
method,
275+
genericTypes.toList(),
276+
);
268277
positionalArguments.forEach(invocation.addPositionalArgument);
269278
namedArguments.forEach(invocation.addNamedArgument);
270279
return invocation;
@@ -381,9 +390,12 @@ abstract class ExpressionBuilder
381390

382391
/// Returns as an [InvocationBuilder] with arguments added.
383392
InvocationBuilder call(
384-
Iterable<ExpressionBuilder> positionalArguments, [
393+
Iterable<ExpressionBuilder> positionalArguments, {
385394
Map<String, ExpressionBuilder> namedArguments,
386-
]);
395+
});
396+
397+
/// Returns the expression casted as [type].
398+
ExpressionBuilder castAs(TypeBuilder type);
387399

388400
/// Return as an [ExpressionBuilder] with `..` appended.
389401
ExpressionBuilder cascade(
@@ -405,9 +417,10 @@ abstract class ExpressionBuilder
405417
/// Returns as an [InvocationBuilder] on [method] of this expression.
406418
InvocationBuilder invoke(
407419
String method,
408-
Iterable<ExpressionBuilder> positionalArguments, [
420+
Iterable<ExpressionBuilder> positionalArguments, {
421+
Iterable<TypeBuilder> genericTypes,
409422
Map<String, ExpressionBuilder> namedArguments,
410-
]);
423+
});
411424

412425
/// Returns as an [ExpressionBuilder] negating using the `!` operator.
413426
ExpressionBuilder negate();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
part of code_builder.src.builders.expression;
6+
7+
class _AsCast extends TopLevelMixin with AbstractExpressionMixin {
8+
final ExpressionBuilder _target;
9+
final TypeBuilder _type;
10+
11+
_AsCast(this._target, this._type);
12+
13+
@override
14+
AstNode buildAst([Scope scope]) => buildExpression(scope);
15+
16+
@override
17+
Expression buildExpression([Scope scope]) {
18+
return astFactory.asExpression(
19+
_target.buildExpression(scope),
20+
$as,
21+
_type.buildType(scope),
22+
);
23+
}
24+
}

lib/src/builders/expression/invocation.dart

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ abstract class AbstractInvocationBuilderMixin implements InvocationBuilder {
2020
}
2121

2222
/// Returns an [ArgumentList] AST.
23-
ArgumentList buildArgumentList([Scope scope]) {
23+
ArgumentList buildArgumentList({
24+
Scope scope,
25+
}) {
2426
final allArguments = <Expression>[];
2527
allArguments.addAll(
26-
_positional.map/*<Expression>*/((e) => e.buildExpression(scope)));
28+
_positional.map/*<Expression>*/((e) => e.buildExpression(scope)),
29+
);
2730
_named.forEach((name, e) {
2831
allArguments.add(astFactory.namedExpression(
2932
astFactory.label(
@@ -51,8 +54,12 @@ abstract class InvocationBuilder
5154
return new _FunctionInvocationBuilder(target);
5255
}
5356

54-
factory InvocationBuilder._on(ExpressionBuilder target, String method) {
55-
return new _MethodInvocationBuilder(target, method);
57+
factory InvocationBuilder._on(
58+
ExpressionBuilder target,
59+
String method,
60+
List<TypeBuilder> generics,
61+
) {
62+
return new _MethodInvocationBuilder(target, method, generics);
5663
}
5764

5865
/// Adds [argument] as a [name]d argument to this method call.
@@ -74,27 +81,34 @@ class _FunctionInvocationBuilder extends Object
7481
return astFactory.functionExpressionInvocation(
7582
_target.buildExpression(scope),
7683
null,
77-
buildArgumentList(scope),
84+
buildArgumentList(scope: scope),
7885
);
7986
}
8087
}
8188

8289
class _MethodInvocationBuilder extends Object
8390
with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin
8491
implements InvocationBuilder {
92+
final List<TypeBuilder> _generics;
8593
final String _method;
8694
final ExpressionBuilder _target;
8795

88-
_MethodInvocationBuilder(this._target, this._method);
96+
_MethodInvocationBuilder(this._target, this._method, this._generics);
8997

9098
@override
9199
Expression buildExpression([Scope scope]) {
92100
return astFactory.methodInvocation(
93101
_target.buildExpression(scope),
94102
$period,
95103
stringIdentifier(_method),
96-
null,
97-
buildArgumentList(scope),
104+
_generics.isNotEmpty
105+
? new TypeArgumentList(
106+
$openBracket,
107+
_generics.map((t) => t.buildType(scope)).toList(),
108+
$closeBracket,
109+
)
110+
: null,
111+
buildArgumentList(scope: scope),
98112
);
99113
}
100114
}

lib/src/builders/type.dart

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,28 @@ part 'type/new_instance.dart';
2323
abstract class AbstractTypeBuilderMixin {
2424
/// Invokes `const` on this type.
2525
NewInstanceBuilder constInstance(
26-
Iterable<ExpressionBuilder> positional, [
27-
Map<String, ExpressionBuilder> named = const {},
28-
]) {
29-
final builder = new NewInstanceBuilder._const(this);
30-
_addArguments(builder, positional, named);
31-
return builder;
32-
}
33-
34-
/// Invokes `const` on this type with a [name]d constructor.
35-
NewInstanceBuilder namedConstInstance(
36-
String name,
37-
Iterable<ExpressionBuilder> positional, [
38-
Map<String, ExpressionBuilder> named = const {},
39-
]) {
40-
final builder = new NewInstanceBuilder._const(this, name);
41-
_addArguments(builder, positional, named);
26+
Iterable<ExpressionBuilder> positionalArguments, {
27+
String constructor,
28+
Map<String, ExpressionBuilder> namedArguments: const {},
29+
}) {
30+
final builder = new NewInstanceBuilder._const(
31+
this,
32+
constructor: constructor,
33+
);
34+
_addArguments(builder, positionalArguments, namedArguments);
4235
return builder;
4336
}
4437

4538
/// Invokes `new` on this type.
4639
NewInstanceBuilder newInstance(
47-
Iterable<ExpressionBuilder> positional, [
48-
Map<String, ExpressionBuilder> named = const {},
49-
]) {
50-
final builder = new NewInstanceBuilder._new(this);
51-
_addArguments(builder, positional, named);
52-
return builder;
53-
}
54-
55-
/// Invokes `new` on this type with a [name]d constructor.
56-
NewInstanceBuilder namedNewInstance(
57-
String name,
58-
Iterable<ExpressionBuilder> positional, [
59-
Map<String, ExpressionBuilder> named = const {},
60-
]) {
61-
final builder = new NewInstanceBuilder._new(this, name);
40+
Iterable<ExpressionBuilder> positional, {
41+
String constructor,
42+
Map<String, ExpressionBuilder> named: const {},
43+
}) {
44+
final builder = new NewInstanceBuilder._new(
45+
this,
46+
constructor: constructor,
47+
);
6248
_addArguments(builder, positional, named);
6349
return builder;
6450
}

lib/src/builders/type/new_instance.dart

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,53 @@ part of code_builder.src.builders.type;
88
///
99
/// See [TypeBuilder]:
1010
/// - [TypeBuilder.constInstance]
11-
/// - [TypeBuilder.namedConstInstance]
1211
/// - [TypeBuilder.newInstance]
13-
/// - [TypeBuilder.namedNewInstance]
1412
abstract class NewInstanceBuilder
1513
implements AnnotationBuilder, InvocationBuilder {
16-
factory NewInstanceBuilder._const(TypeBuilder type, [String name]) {
17-
return new _NewInvocationBuilderImpl(Keyword.CONST, type, name);
14+
factory NewInstanceBuilder._const(
15+
TypeBuilder type, {
16+
String constructor,
17+
}) {
18+
return new _NewInvocationBuilderImpl(
19+
Keyword.CONST,
20+
type,
21+
constructor,
22+
);
1823
}
1924

20-
factory NewInstanceBuilder._new(TypeBuilder type, [String name]) {
21-
return new _NewInvocationBuilderImpl(Keyword.NEW, type, name);
25+
factory NewInstanceBuilder._new(
26+
TypeBuilder type, {
27+
String constructor,
28+
}) {
29+
return new _NewInvocationBuilderImpl(
30+
Keyword.NEW,
31+
type,
32+
constructor,
33+
);
2234
}
2335
}
2436

2537
class _NewInvocationBuilderImpl extends Object
2638
with AbstractExpressionMixin, AbstractInvocationBuilderMixin, TopLevelMixin
2739
implements NewInstanceBuilder {
28-
final String _name;
40+
final String _constructor;
2941
final Keyword _keyword;
3042
final TypeBuilder _type;
3143

32-
_NewInvocationBuilderImpl(this._keyword, this._type, [this._name]);
44+
_NewInvocationBuilderImpl(
45+
this._keyword,
46+
this._type,
47+
this._constructor,
48+
);
3349

3450
@override
3551
Annotation buildAnnotation([Scope scope]) {
3652
return astFactory.annotation(
3753
$at,
3854
_type.buildType(scope).name,
3955
$period,
40-
_name != null ? stringIdentifier(_name) : null,
41-
buildArgumentList(scope),
56+
_constructor != null ? stringIdentifier(_constructor) : null,
57+
buildArgumentList(scope: scope),
4258
);
4359
}
4460

@@ -48,10 +64,10 @@ class _NewInvocationBuilderImpl extends Object
4864
new KeywordToken(_keyword, 0),
4965
astFactory.constructorName(
5066
_type.buildType(scope),
51-
_name != null ? $period : null,
52-
_name != null ? stringIdentifier(_name) : null,
67+
_constructor != null ? $period : null,
68+
_constructor != null ? stringIdentifier(_constructor) : null,
5369
),
54-
buildArgumentList(scope),
70+
buildArgumentList(scope: scope),
5571
);
5672
}
5773
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: code_builder
2-
version: 1.0.0-beta+2
2+
version: 1.0.0-beta+3
33
description: A fluent API for generating Dart code
44
author: Dart Team <misc@dartlang.org>
55
homepage: https://github.com/dart-lang/code_builder

0 commit comments

Comments
 (0)