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

Commit 709b663

Browse files
authored
Fix a number of issues. (#140)
* Fix a number of issues. * OK, add some tests. * Dartfmt.
1 parent a9d0ce5 commit 709b663

File tree

8 files changed

+247
-8
lines changed

8 files changed

+247
-8
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 2.0.0-alpha+3
2+
3+
* Added `{new|const}InstanceNamed` to `Expression` [#135](https://github.com/dart-lang/code_builder/issues/135).
4+
* Also added a `typeArguments` option to all invocations.
5+
* **BUG FIX**: `Block` now implements `Code` [#136](https://github.com/dart-lang/code_builder/issues/136).
6+
* Added `assign{...}` variants to `Expression` [#137](https://github.com/dart-lang/code_builder/issues/137).
7+
* Added `.awaited` and `.returned` to `Expression` [#138](https://github.com/dart-lang/code_builder/issues/138).
8+
* **BUG FIX**: `new DartEmitter.scoped()` applies prefixing [#139](https://github.com/dart-lang/code_builder/issues/139).
9+
110
## 2.0.0-alpha+2
211

312
* Upgraded `build_runner` from `^0.3.0` to `>=0.4.0 <0.6.0`.

lib/src/emitter.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ class DartEmitter extends Object
5858
/// May specify an [Allocator] to use for symbols, otherwise uses a no-op.
5959
DartEmitter([this.allocator = Allocator.none]);
6060

61-
/// Creates a new instance of [DartEmitter] with a default [Allocator].
62-
factory DartEmitter.scoped() => new DartEmitter(new Allocator());
61+
/// Creates a new instance of [DartEmitter] with simple automatic imports.
62+
factory DartEmitter.scoped() {
63+
return new DartEmitter(new Allocator.simplePrefixing());
64+
}
6365

6466
@override
6567
visitAnnotation(Annotation spec, [StringSink output]) {

lib/src/specs/code.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ abstract class Code implements Spec {
4848
}
4949

5050
/// Represents blocks of statements of Dart code.
51-
abstract class Block implements Built<Block, BlockBuilder>, Spec {
51+
abstract class Block implements Built<Block, BlockBuilder>, Code, Spec {
5252
factory Block([void updates(BlockBuilder b)]) = _$Block;
5353

5454
Block._();

lib/src/specs/expression.dart

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,89 @@ abstract class Expression implements Spec {
3939
return new BinaryExpression._(toExpression(), other, '&&');
4040
}
4141

42+
/// This expression preceding by `await`.
43+
Expression get awaited {
44+
return new BinaryExpression._(
45+
const LiteralExpression._('await'),
46+
this,
47+
'',
48+
);
49+
}
50+
51+
/// Return `{other} = {this}`.
52+
Expression assign(Expression other) {
53+
return new BinaryExpression._(
54+
other,
55+
this,
56+
'=',
57+
);
58+
}
59+
60+
/// Return `{other} ??= {this}`.
61+
Expression assignNullAware(Expression other) {
62+
return new BinaryExpression._(
63+
other,
64+
this,
65+
'??=',
66+
);
67+
}
68+
69+
/// Return `var {name} = {this}`.
70+
Expression assignVar(String name, [Reference type]) {
71+
return new BinaryExpression._(
72+
type == null
73+
? new LiteralExpression._('var $name')
74+
: new BinaryExpression._(
75+
type.toExpression(),
76+
new LiteralExpression._(name),
77+
'',
78+
),
79+
this,
80+
'=',
81+
);
82+
}
83+
84+
/// Return `final {name} = {this}`.
85+
Expression assignFinal(String name, [Reference type]) {
86+
return new BinaryExpression._(
87+
type == null
88+
? const LiteralExpression._('final')
89+
: new BinaryExpression._(
90+
const LiteralExpression._('final'),
91+
type.toExpression(),
92+
'',
93+
),
94+
this,
95+
'$name =',
96+
);
97+
}
98+
99+
/// Return `const {name} = {this}`.
100+
Expression assignConst(String name, [Reference type]) {
101+
return new BinaryExpression._(
102+
type == null
103+
? const LiteralExpression._('const')
104+
: new BinaryExpression._(
105+
const LiteralExpression._('const'),
106+
type.toExpression(),
107+
'',
108+
),
109+
this,
110+
'$name =',
111+
);
112+
}
113+
42114
/// Call this expression as a method.
43115
Expression call(
44116
List<Expression> positionalArguments, [
45117
Map<String, Expression> namedArguments = const {},
118+
List<Reference> typeArguments = const [],
46119
]) {
47120
return new InvokeExpression._(
48121
this,
49122
positionalArguments,
50123
namedArguments,
124+
typeArguments,
51125
);
52126
}
53127

@@ -65,27 +139,74 @@ abstract class Expression implements Spec {
65139
Expression newInstance(
66140
List<Expression> positionalArguments, [
67141
Map<String, Expression> namedArguments = const {},
142+
List<Reference> typeArguments = const [],
68143
]) {
69144
return new InvokeExpression._new(
70145
this,
71146
positionalArguments,
72147
namedArguments,
148+
typeArguments,
149+
null,
150+
);
151+
}
152+
153+
/// Returns a new instance of this expression with a named constructor.
154+
Expression newInstanceNamed(
155+
String name,
156+
List<Expression> positionalArguments, [
157+
Map<String, Expression> namedArguments = const {},
158+
List<Reference> typeArguments = const [],
159+
]) {
160+
return new InvokeExpression._new(
161+
this,
162+
positionalArguments,
163+
namedArguments,
164+
typeArguments,
165+
name,
73166
);
74167
}
75168

76169
/// Returns a const instance of this expression.
77170
Expression constInstance(
78171
List<Expression> positionalArguments, [
79172
Map<String, Expression> namedArguments = const {},
173+
List<Reference> typeArguments = const [],
80174
]) {
81175
return new InvokeExpression._const(
82176
this,
83177
positionalArguments,
84178
namedArguments,
179+
typeArguments,
180+
null,
85181
);
86182
}
87183

88-
/// May be overriden to support other types implementing [Expression].
184+
/// Returns a const instance of this expression with a named constructor.
185+
Expression constInstanceNamed(
186+
String name,
187+
List<Expression> positionalArguments, [
188+
Map<String, Expression> namedArguments = const {},
189+
List<Reference> typeArguments = const [],
190+
]) {
191+
return new InvokeExpression._const(
192+
this,
193+
positionalArguments,
194+
namedArguments,
195+
typeArguments,
196+
name,
197+
);
198+
}
199+
200+
/// This expression preceding by `return`.
201+
Expression get returned {
202+
return new BinaryExpression._(
203+
const LiteralExpression._('return'),
204+
this,
205+
'',
206+
);
207+
}
208+
209+
/// May be overridden to support other types implementing [Expression].
89210
@visibleForOverriding
90211
Expression toExpression() => this;
91212
}
@@ -171,6 +292,16 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
171292
break;
172293
}
173294
expression.target.accept(this, output);
295+
if (expression.name != null) {
296+
output..write('.')..write(expression.name);
297+
}
298+
if (expression.typeArguments.isNotEmpty) {
299+
output.write('<');
300+
visitAll<Reference>(expression.typeArguments, output, (type) {
301+
type.accept(this, output);
302+
});
303+
output.write('>');
304+
}
174305
output.write('(');
175306
visitAll<Spec>(expression.positionalArguments, output, (spec) {
176307
spec.accept(this, output);

lib/src/specs/expression/invoke.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,34 @@ class InvokeExpression extends Expression {
1313
final InvokeExpressionType type;
1414

1515
final List<Expression> positionalArguments;
16-
1716
final Map<String, Expression> namedArguments;
17+
final List<Reference> typeArguments;
18+
final String name;
1819

1920
const InvokeExpression._(
2021
this.target,
2122
this.positionalArguments, [
2223
this.namedArguments = const {},
24+
this.typeArguments,
2325
])
24-
: type = null;
26+
: type = null,
27+
name = null;
2528

2629
const InvokeExpression._new(
2730
this.target,
2831
this.positionalArguments, [
2932
this.namedArguments = const {},
33+
this.typeArguments,
34+
this.name,
3035
])
3136
: type = InvokeExpressionType.newInstance;
3237

3338
const InvokeExpression._const(
3439
this.target,
3540
this.positionalArguments, [
3641
this.namedArguments = const {},
42+
this.typeArguments,
43+
this.name,
3744
])
3845
: type = InvokeExpressionType.constInstance;
3946

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: 2.0.0-alpha+2
2+
version: 2.0.0-alpha+3
33
description: A fluent API for generating Dart code
44
author: Dart Team <[email protected]>
55
homepage: https://github.com/dart-lang/code_builder

test/specs/code/expression_test.dart

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ void main() {
7878
);
7979
});
8080

81+
test('should emit invoking new named constructor', () {
82+
expect(
83+
refer('Foo').newInstanceNamed('bar', []),
84+
equalsDart('new Foo.bar()'),
85+
);
86+
});
87+
88+
test('should emit invoking const Type()', () {
89+
expect(
90+
refer('Object').constInstance([]),
91+
equalsDart('const Object()'),
92+
);
93+
});
94+
8195
test('should emit invoking a property accessor', () {
8296
expect(refer('foo').property('bar'), equalsDart('foo.bar'));
8397
});
@@ -132,4 +146,80 @@ void main() {
132146
equalsDart('foo(1, bar: 2, baz: 3)'),
133147
);
134148
});
149+
150+
test('should emit invoking a method with a single type argument', () {
151+
expect(
152+
refer('foo').call(
153+
[],
154+
{},
155+
[
156+
refer('String'),
157+
],
158+
),
159+
equalsDart('foo<String>()'),
160+
);
161+
});
162+
163+
test('should emit invoking a method with type arguments', () {
164+
expect(
165+
refer('foo').call(
166+
[],
167+
{},
168+
[
169+
refer('String'),
170+
refer('int'),
171+
],
172+
),
173+
equalsDart('foo<String, int>()'),
174+
);
175+
});
176+
177+
test('should emit an assignment', () {
178+
expect(
179+
literalTrue.assign(refer('foo')),
180+
equalsDart('foo = true'),
181+
);
182+
});
183+
184+
test('should emit assigning to a var', () {
185+
expect(
186+
literalTrue.assignVar('foo'),
187+
equalsDart('var foo = true'),
188+
);
189+
});
190+
191+
test('should emit assigning to a type', () {
192+
expect(
193+
literalTrue.assignVar('foo', refer('bool')),
194+
equalsDart('bool foo = true'),
195+
);
196+
});
197+
198+
test('should emit assigning to a final', () {
199+
expect(
200+
literalTrue.assignFinal('foo'),
201+
equalsDart('final foo = true'),
202+
);
203+
});
204+
205+
test('should emit assigning to a const', () {
206+
expect(
207+
literalTrue.assignConst('foo'),
208+
equalsDart('const foo = true'),
209+
);
210+
});
211+
212+
test('should emit await', () {
213+
expect(
214+
refer('future').awaited,
215+
equalsDart('await future'),
216+
);
217+
});
218+
219+
test('should emit return', () {
220+
expect(
221+
literalNull.returned,
222+
equalsDart('return null'),
223+
);
224+
});
135225
}

test/specs/file_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void main() {
8888
import 'dart:collection';
8989
9090
final test = new LinkedHashMap();
91-
''', new DartEmitter.scoped()),
91+
''', new DartEmitter(new Allocator())),
9292
);
9393
});
9494

0 commit comments

Comments
 (0)