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

Commit f635ab6

Browse files
authored
Add support for trailing commas in Emitter (#376)
1 parent e082adb commit f635ab6

File tree

8 files changed

+70
-34
lines changed

8 files changed

+70
-34
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Only emit `late` keyword when using null safety syntax.
44
* Use implicit `const` when assigning to a `declareConst` variable.
55
* Deprecate `assignVar`, `assignConst`, and `assignFinal`.
6+
* Add trailing commas to any parameter list, argument list, or collection
7+
literal which has more than one element.
68

79
## 4.2.0
810

lib/src/emitter.dart

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,15 @@ class DartEmitter extends Object
213213
..write(spec.name);
214214
}
215215
output.write('(');
216+
final hasMultipleParameters =
217+
spec.requiredParameters.length + spec.optionalParameters.length > 1;
216218
if (spec.requiredParameters.isNotEmpty) {
217219
var count = 0;
218220
for (final p in spec.requiredParameters) {
219221
count++;
220222
_visitParameter(p, output);
221-
if (spec.requiredParameters.length != count ||
223+
if (hasMultipleParameters ||
224+
spec.requiredParameters.length != count ||
222225
spec.optionalParameters.isNotEmpty) {
223226
output.write(', ');
224227
}
@@ -235,7 +238,7 @@ class DartEmitter extends Object
235238
for (final p in spec.optionalParameters) {
236239
count++;
237240
_visitParameter(p, output, optional: true, named: named);
238-
if (spec.optionalParameters.length != count) {
241+
if (hasMultipleParameters || spec.optionalParameters.length != count) {
239242
output.write(', ');
240243
}
241244
}
@@ -453,20 +456,30 @@ class DartEmitter extends Object
453456
out.write('>');
454457
}
455458
out.write('(');
459+
final needsTrailingComma = spec.requiredParameters.length +
460+
spec.optionalParameters.length +
461+
spec.namedRequiredParameters.length +
462+
spec.namedParameters.length >
463+
1;
456464
visitAll<Reference>(spec.requiredParameters, out, (spec) {
457465
spec.accept(this, out);
458466
});
459467
final hasNamedParameters = spec.namedRequiredParameters.isNotEmpty ||
460468
spec.namedParameters.isNotEmpty;
461469
if (spec.requiredParameters.isNotEmpty &&
462-
(spec.optionalParameters.isNotEmpty || hasNamedParameters)) {
470+
(needsTrailingComma ||
471+
spec.optionalParameters.isNotEmpty ||
472+
hasNamedParameters)) {
463473
out.write(', ');
464474
}
465475
if (spec.optionalParameters.isNotEmpty) {
466476
out.write('[');
467477
visitAll<Reference>(spec.optionalParameters, out, (spec) {
468478
spec.accept(this, out);
469479
});
480+
if (needsTrailingComma) {
481+
out.write(', ');
482+
}
470483
out.write(']');
471484
} else if (hasNamedParameters) {
472485
out.write('{');
@@ -487,6 +500,9 @@ class DartEmitter extends Object
487500
..write(' ')
488501
..write(name);
489502
});
503+
if (needsTrailingComma) {
504+
out.write(', ');
505+
}
490506
out.write('}');
491507
}
492508
out.write(')');
@@ -526,12 +542,15 @@ class DartEmitter extends Object
526542
}
527543
visitTypeParameters(spec.types.map((r) => r.type), output);
528544
output.write('(');
545+
final hasMultipleParameters =
546+
spec.requiredParameters.length + spec.optionalParameters.length > 1;
529547
if (spec.requiredParameters.isNotEmpty) {
530548
var count = 0;
531549
for (final p in spec.requiredParameters) {
532550
count++;
533551
_visitParameter(p, output);
534-
if (spec.requiredParameters.length != count ||
552+
if (hasMultipleParameters ||
553+
spec.requiredParameters.length != count ||
535554
spec.optionalParameters.isNotEmpty) {
536555
output.write(', ');
537556
}
@@ -548,7 +567,8 @@ class DartEmitter extends Object
548567
for (final p in spec.optionalParameters) {
549568
count++;
550569
_visitParameter(p, output, optional: true, named: named);
551-
if (spec.optionalParameters.length != count) {
570+
if (hasMultipleParameters ||
571+
spec.optionalParameters.length != count) {
552572
output.write(', ');
553573
}
554574
}

lib/src/specs/expression.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,11 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
497497
..write(': ');
498498
expression.namedArguments[name]!.accept(this, out);
499499
});
500+
final argumentCount = expression.positionalArguments.length +
501+
expression.namedArguments.length;
502+
if (argumentCount > 1) {
503+
out.write(', ');
504+
}
500505
return out..write(')');
501506
});
502507
}
@@ -535,6 +540,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
535540
visitAll<Object?>(expression.values, out, (value) {
536541
_acceptLiteral(value, out);
537542
});
543+
if (expression.values.length > 1) {
544+
out.write(', ');
545+
}
538546
return out..write(']');
539547
});
540548
}
@@ -556,6 +564,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
556564
visitAll<Object?>(expression.values, out, (value) {
557565
_acceptLiteral(value, out);
558566
});
567+
if (expression.values.length > 1) {
568+
out.write(', ');
569+
}
559570
return out..write('}');
560571
});
561572
}
@@ -585,6 +596,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor<StringSink> {
585596
out.write(': ');
586597
_acceptLiteral(value, out);
587598
});
599+
if (expression.values.length > 1) {
600+
out.write(', ');
601+
}
588602
return out..write('}');
589603
});
590604
}

test/const_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ void main() {
1717

1818
test('expression', () {
1919
expect(constMap, equalsDart(r'''
20-
const {'list': [], 'duration': Duration()}'''));
20+
const {'list': [], 'duration': Duration(), }'''));
2121
});
2222

2323
test('assignConst', () {
2424
expect(
2525
// ignore: deprecated_member_use_from_same_package
2626
constMap.assignConst('constField'),
2727
equalsDart(r'''
28-
const constField = {'list': [], 'duration': Duration()}''',
28+
const constField = {'list': [], 'duration': Duration(), }''',
2929
DartEmitter.scoped()),
3030
);
3131
});
@@ -34,7 +34,7 @@ void main() {
3434
expect(
3535
declareConst('constField').assign(constMap),
3636
equalsDart(r'''
37-
const constField = {'list': [], 'duration': Duration()}''',
37+
const constField = {'list': [], 'duration': Duration(), }''',
3838
DartEmitter.scoped()),
3939
);
4040
});
@@ -43,7 +43,7 @@ void main() {
4343
expect(
4444
declareVar('varField').assign(constMap),
4545
equalsDart(r'''
46-
var varField = const {'list': [], 'duration': Duration()}''',
46+
var varField = const {'list': [], 'duration': Duration(), }''',
4747
DartEmitter.scoped()));
4848
});
4949

test/e2e/injection_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void main() {
4545
final Module _module;
4646
4747
@override
48-
Thing getThing() => Thing(_module.get1(), _module.get2());
48+
Thing getThing() => Thing(_module.get1(), _module.get2(), );
4949
}
5050
'''),
5151
);
@@ -59,7 +59,7 @@ void main() {
5959
final _i2.Module _module;
6060
6161
@override
62-
_i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2());
62+
_i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2(), );
6363
}
6464
''', DartEmitter(allocator: Allocator.simplePrefixing())),
6565
);

test/specs/class_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ void main() {
312312
);
313313
});
314314

315-
test('should create a class with method parameters', () {
315+
test('should create a class with a constructor with parameters', () {
316316
expect(
317317
Class((b) => b
318318
..name = 'Foo'
@@ -328,7 +328,7 @@ void main() {
328328
])))),
329329
equalsDart(r'''
330330
class Foo {
331-
Foo(a, b, {c});
331+
Foo(a, b, {c, });
332332
}
333333
'''),
334334
);
@@ -355,7 +355,7 @@ void main() {
355355
])))),
356356
equalsDart(r'''
357357
class Foo {
358-
Foo(this.a, this.b, {this.c});
358+
Foo(this.a, this.b, {this.c, });
359359
}
360360
'''),
361361
);
@@ -382,7 +382,7 @@ void main() {
382382
])))),
383383
equalsDart(r'''
384384
class Foo {
385-
Foo(super.a, super.b, {super.c});
385+
Foo(super.a, super.b, {super.c, });
386386
}
387387
'''),
388388
);

test/specs/code/expression_test.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ void main() {
9696
refer('three'): 3,
9797
refer('Map').newInstance([]): null,
9898
}),
99-
equalsDart(r"{1: 'one', 2: two, three: 3, Map(): null}"),
99+
equalsDart(r"{1: 'one', 2: two, three: 3, Map(): null, }"),
100100
);
101101
});
102102

@@ -110,7 +110,7 @@ void main() {
110110
null,
111111
refer('Map').newInstance([])
112112
]),
113-
equalsDart('[[], {}, true, null, Map()]'),
113+
equalsDart('[[], {}, true, null, Map(), ]'),
114114
);
115115
});
116116

@@ -125,7 +125,7 @@ void main() {
125125
null,
126126
refer('Map').newInstance([])
127127
]),
128-
equalsDart('{[], {}, true, null, Map()}'),
128+
equalsDart('{[], {}, true, null, Map(), }'),
129129
);
130130
});
131131

@@ -190,7 +190,7 @@ void main() {
190190
literal(2),
191191
literal(3),
192192
]),
193-
equalsDart('foo(1, 2, 3)'),
193+
equalsDart('foo(1, 2, 3, )'),
194194
);
195195
});
196196

@@ -209,7 +209,7 @@ void main() {
209209
'bar': literal(1),
210210
'baz': literal(2),
211211
}),
212-
equalsDart('foo(bar: 1, baz: 2)'),
212+
equalsDart('foo(bar: 1, baz: 2, )'),
213213
);
214214
});
215215

@@ -221,7 +221,7 @@ void main() {
221221
'bar': literal(2),
222222
'baz': literal(3),
223223
}),
224-
equalsDart('foo(1, bar: 2, baz: 3)'),
224+
equalsDart('foo(1, bar: 2, baz: 3, )'),
225225
);
226226
});
227227

@@ -287,7 +287,7 @@ void main() {
287287
FunctionType((b) => b
288288
..requiredParameters.add(refer('String'))
289289
..optionalParameters.add(refer('int'))),
290-
equalsDart('Function(String, [int])'),
290+
equalsDart('Function(String, [int, ])'),
291291
);
292292
});
293293

@@ -298,7 +298,7 @@ void main() {
298298
'x': refer('int'),
299299
'y': refer('int'),
300300
})),
301-
equalsDart('Function({int x, int y})'),
301+
equalsDart('Function({int x, int y, })'),
302302
);
303303
});
304304

@@ -313,7 +313,7 @@ void main() {
313313
..namedParameters.addAll({
314314
'y': refer('int'),
315315
})),
316-
equalsDart('Function({required int x, int y})'),
316+
equalsDart('Function({required int x, int y, })'),
317317
);
318318
});
319319

@@ -324,7 +324,7 @@ void main() {
324324
'x': refer('int'),
325325
'y': refer('int'),
326326
})),
327-
equalsDart('Function({required int x, required int y})'),
327+
equalsDart('Function({required int x, required int y, })'),
328328
);
329329
});
330330

@@ -373,7 +373,7 @@ void main() {
373373
literalString('foo'),
374374
Method((b) => b..body = literalTrue.code).closure,
375375
]),
376-
equalsDart("map.putIfAbsent('foo', () => true)"),
376+
equalsDart("map.putIfAbsent('foo', () => true, )"),
377377
);
378378
});
379379

@@ -385,7 +385,7 @@ void main() {
385385
..types.add(refer('T'))
386386
..body = literalTrue.code).genericClosure,
387387
]),
388-
equalsDart("map.putIfAbsent('foo', <T>() => true)"),
388+
equalsDart("map.putIfAbsent('foo', <T>() => true, )"),
389389
);
390390
});
391391

0 commit comments

Comments
 (0)