Skip to content

Commit 5f05e58

Browse files
authored
Format metadata on patterns in for loops. (#1183)
Also fix a couple of minor issues I noticed when testing against the Dart SDK repo: - Gracefully handle empty switch expressions. - Handle sync* and async* functions with => bodies.
1 parent 7fd45d6 commit 5f05e58

File tree

5 files changed

+142
-6
lines changed

5 files changed

+142
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 2.2.5-dev
22

33
* Format patterns and related features.
4+
* Handle `sync*` and `async*` functions with `=>` bodies.
45
* Allow switch statements where all case bodies are on the same line as the
56
case when they all fit.
67
* Fix bug where parameter metadata wouldn't always split when it should.

lib/src/source_visitor.dart

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,8 +1071,10 @@ class SourceVisitor extends ThrowingAstVisitor {
10711071
// Space after the parameter list.
10721072
space();
10731073

1074-
// The "async" or "sync" keyword.
1075-
token(node.keyword, after: space);
1074+
// The "async" or "sync" keyword and "*".
1075+
token(node.keyword);
1076+
token(node.star);
1077+
if (node.keyword != null || node.star != null) space();
10761078

10771079
// Try to keep the "(...) => " with the start of the body for anonymous
10781080
// functions.
@@ -1507,6 +1509,7 @@ class SourceVisitor extends ThrowingAstVisitor {
15071509
@override
15081510
void visitForEachPartsWithPattern(ForEachPartsWithPattern node) {
15091511
builder.startBlockArgumentNesting();
1512+
visitNodes(node.metadata, between: split, after: split);
15101513
token(node.keyword);
15111514
space();
15121515
visit(node.pattern);
@@ -1524,7 +1527,7 @@ class SourceVisitor extends ThrowingAstVisitor {
15241527
builder.startRule();
15251528

15261529
var declaration = node.variables;
1527-
visitMetadata(declaration.metadata);
1530+
visitNodes(declaration.metadata, between: split, after: split);
15281531
modifier(declaration.keyword);
15291532
visit(declaration.type, after: space);
15301533

@@ -1547,8 +1550,18 @@ class SourceVisitor extends ThrowingAstVisitor {
15471550
@override
15481551
void visitForPartsWithPattern(ForPartsWithPattern node) {
15491552
builder.startBlockArgumentNesting();
1550-
visit(node.variables);
1553+
builder.nestExpression();
1554+
1555+
var declaration = node.variables;
1556+
visitNodes(declaration.metadata, between: split, after: split);
1557+
token(declaration.keyword);
1558+
space();
1559+
visit(declaration.pattern);
1560+
_visitAssignment(declaration.equals, declaration.expression);
1561+
1562+
builder.unnest();
15511563
builder.endBlockArgumentNesting();
1564+
15521565
_visitForPartsFromLeftSeparator(node);
15531566
}
15541567

@@ -2714,7 +2727,10 @@ class SourceVisitor extends ThrowingAstVisitor {
27142727

27152728
visitCommaSeparatedNodes(node.cases, between: split);
27162729

2717-
var hasTrailingComma = node.cases.last.commaAfter != null;
2730+
// A switch with no cases isn't syntactically valid, but handle it
2731+
// gracefully instead of crashing.
2732+
var hasTrailingComma =
2733+
node.cases.isNotEmpty && node.cases.last.commaAfter != null;
27182734
_endBody(node.rightBracket, forceSplit: hasTrailingComma);
27192735
}
27202736

test/whitespace/functions.unit

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,22 @@ main()sync *{var lambda = ()sync *{};}
7272
main() sync* {
7373
var lambda = () sync* {};
7474
}
75+
>>> sync* function with arrow body
76+
main()sync * => [];
77+
<<<
78+
main() sync* => [];
79+
>>> sync* getter with arrow body
80+
Iterable get main sync * => [];
81+
<<<
82+
Iterable get main sync* => [];
83+
>>> async* function with arrow body
84+
main()async * => [];
85+
<<<
86+
main() async* => [];
87+
>>> async* getter with arrow body
88+
Stream get main async * => [];
89+
<<<
90+
Stream get main async* => [];
7591
>>> trailing comma in single parameter list
7692
function(parameter , ) {;}
7793
<<<

test/whitespace/metadata.unit

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,105 @@ main() {
318318
;
319319
}
320320
}
321+
>>> single metadata on for loop
322+
main() {
323+
for ( @a var i = x;;) {;}
324+
}
325+
<<<
326+
main() {
327+
for (@a var i = x;;) {
328+
;
329+
}
330+
}
331+
>>> multiple metadata on for loop
332+
main() {
333+
for ( @a @b var i = x;;) {;}
334+
}
335+
<<<
336+
main() {
337+
for (@a @b var i = x;;) {
338+
;
339+
}
340+
}
341+
>>> long metadata on for loop
342+
main() {
343+
for (@Annotation @VeryLongMetadataAnnotation(1, 2) var i = veryLong.iterator + expression;;) {;}
344+
}
345+
<<<
346+
main() {
347+
for (@Annotation
348+
@VeryLongMetadataAnnotation(1, 2)
349+
var i = veryLong.iterator +
350+
expression;;) {
351+
;
352+
}
353+
}
354+
>>> single metadata on pattern for-in loop
355+
main() {
356+
for ( @a var [i] in list) {;}
357+
}
358+
<<<
359+
main() {
360+
for (@a var [i] in list) {
361+
;
362+
}
363+
}
364+
>>> multiple metadata on pattern for-in loop
365+
main() {
366+
for ( @a @b var [i] in list) {;}
367+
}
368+
<<<
369+
main() {
370+
for (@a @b var [i] in list) {
371+
;
372+
}
373+
}
374+
>>> long metadata on pattern for-in loop
375+
main() {
376+
for (@Annotation @VeryLongMetadataAnnotation(1, 2) var [i] in veryLong.iterator + expression) {;}
377+
}
378+
<<<
379+
main() {
380+
for (@Annotation
381+
@VeryLongMetadataAnnotation(1, 2)
382+
var [i] in veryLong.iterator +
383+
expression) {
384+
;
385+
}
386+
}
387+
>>> single metadata on pattern for loop
388+
main() {
389+
for ( @a var [i] = x;;) {;}
390+
}
391+
<<<
392+
main() {
393+
for (@a var [i] = x;;) {
394+
;
395+
}
396+
}
397+
>>> multiple metadata on pattern for loop
398+
main() {
399+
for ( @a @b var [i] = x;;) {;}
400+
}
401+
<<<
402+
main() {
403+
for (@a @b var [i] = x;;) {
404+
;
405+
}
406+
}
407+
>>> long metadata on pattern for loop
408+
main() {
409+
for (@Annotation @VeryLongMetadataAnnotation(1, 2) var [i] = veryLong.iterator + expression;;) {;}
410+
}
411+
<<<
412+
main() {
413+
for (@Annotation
414+
@VeryLongMetadataAnnotation(1, 2)
415+
var [i] = veryLong.iterator +
416+
expression;;) {
417+
;
418+
}
419+
}
321420
>>> metadata on enum cases
322421
enum Foo { a, @meta b, @meta1 @meta2 c}
323422
<<<

test/whitespace/switch.stmt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,8 @@ switch (obj) {
290290
case 's'.length:
291291
case 1 is int:
292292
case 1 is! int:
293-
}
293+
}
294+
>>> empty switch expression (error but handle gracefully)
295+
var x = switch(y) {};
296+
<<<
297+
var x = switch (y) { };

0 commit comments

Comments
 (0)