Skip to content

Commit e68ae72

Browse files
authored
Format record pattern. (#1371)
* Format record pattern. * Add an extra switch case. * Remove unnecessary parameter. * Change switch cases to write out the edge cases instead. * Fix comments and revert switch.
1 parent 254c796 commit e68ae72

File tree

5 files changed

+260
-13
lines changed

5 files changed

+260
-13
lines changed

lib/src/ast_extensions.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ extension PatternExtensions on DartPattern {
392392
elements.canSplit(rightBracket),
393393
MapPattern(:var elements, :var rightBracket) =>
394394
elements.canSplit(rightBracket),
395+
RecordPattern(:var fields, :var rightParenthesis) =>
396+
fields.canSplit(rightParenthesis),
395397
_ => false,
396398
};
397399
}

lib/src/front_end/ast_node_visitor.dart

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,7 +1355,19 @@ class AstNodeVisitor extends ThrowingAstVisitor<Piece> with PieceFactory {
13551355

13561356
@override
13571357
Piece visitPatternField(PatternField node) {
1358-
throw UnimplementedError();
1358+
return buildPiece((b) {
1359+
b.visit(node.name);
1360+
b.visit(node.pattern);
1361+
});
1362+
}
1363+
1364+
@override
1365+
Piece visitPatternFieldName(PatternFieldName node) {
1366+
return buildPiece((b) {
1367+
b.token(node.name);
1368+
b.token(node.colon);
1369+
if (node.name != null) b.space();
1370+
});
13591371
}
13601372

13611373
@override
@@ -1424,27 +1436,21 @@ class AstNodeVisitor extends ThrowingAstVisitor<Piece> with PieceFactory {
14241436

14251437
@override
14261438
Piece visitRecordLiteral(RecordLiteral node) {
1427-
ListStyle style;
1428-
if (node.fields.length == 1 && node.fields[0] is! NamedExpression) {
1429-
// Single-element records always have a trailing comma, unless the single
1430-
// element is a named field.
1431-
style = const ListStyle(commas: Commas.alwaysTrailing);
1432-
} else {
1433-
style = const ListStyle(commas: Commas.trailing);
1434-
}
1435-
1436-
return createCollection(
1439+
return createRecord(
14371440
constKeyword: node.constKeyword,
14381441
node.leftParenthesis,
14391442
node.fields,
14401443
node.rightParenthesis,
1441-
style: style,
14421444
);
14431445
}
14441446

14451447
@override
14461448
Piece visitRecordPattern(RecordPattern node) {
1447-
throw UnimplementedError();
1449+
return createRecord(
1450+
node.leftParenthesis,
1451+
node.fields,
1452+
node.rightParenthesis,
1453+
);
14481454
}
14491455

14501456
@override

lib/src/front_end/piece_factory.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,53 @@ mixin PieceFactory {
702702
);
703703
}
704704

705+
/// Creates a [ListPiece] for a record literal or pattern.
706+
Piece createRecord(
707+
Token leftParenthesis,
708+
List<AstNode> fields,
709+
Token rightParenthesis, {
710+
Token? constKeyword,
711+
}) {
712+
var style = switch (fields) {
713+
// Record types or patterns with a single named field don't add a trailing
714+
// comma unless it's split, like:
715+
//
716+
// ({int n}) x;
717+
//
718+
// Or:
719+
//
720+
// if (obj case (name: value)) {
721+
// ;
722+
// }
723+
[PatternField(name: _?)] => const ListStyle(commas: Commas.trailing),
724+
[NamedExpression()] => const ListStyle(commas: Commas.trailing),
725+
726+
// Record types or patterns with a single positional field always have a
727+
// trailing comma to disambiguate from parenthesized expressions or
728+
// patterns, like:
729+
//
730+
// (int,) x;
731+
//
732+
// Or:
733+
//
734+
// if (obj case (pattern,)) {
735+
// ;
736+
// }
737+
[_] => const ListStyle(commas: Commas.alwaysTrailing),
738+
739+
// Record types or patterns with multiple fields have regular trailing
740+
// commas when split.
741+
_ => const ListStyle(commas: Commas.trailing)
742+
};
743+
return createCollection(
744+
constKeyword: constKeyword,
745+
leftParenthesis,
746+
fields,
747+
rightParenthesis,
748+
style: style,
749+
);
750+
}
751+
705752
/// Creates a class, enum, extension, mixin, or mixin application class
706753
/// declaration.
707754
///

test/pattern/record.stmt

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
40 columns |
2+
>>> Basic record switch.
3+
switch (obj) {
4+
case ( ) :
5+
case ( value , ) :
6+
case ( : var x , ) :
7+
case ( name : var x , ) :
8+
case ( first , second , third ) :
9+
case ( first : 1 , 2 , third : 3 ) :
10+
case ( : var x , : var y ) :
11+
ok;
12+
}
13+
<<<
14+
switch (obj) {
15+
case ():
16+
case (value,):
17+
case (:var x):
18+
case (name: var x):
19+
case (first, second, third):
20+
case (first: 1, 2, third: 3):
21+
case (:var x, :var y):
22+
ok;
23+
}
24+
>>> Unsplit single-element record, with trailing comma.
25+
if (obj case (pattern,)) {;}
26+
<<<
27+
if (obj case (pattern,)) {
28+
;
29+
}
30+
>>> Remove trailing comma from single named field.
31+
if (obj case (name: value,)) {;}
32+
<<<
33+
if (obj case (name: value)) {
34+
;
35+
}
36+
>>> Split single-element record after ",".
37+
if (obj case (veryLongRecordField____________,)) {;}
38+
<<<
39+
if (obj case (
40+
veryLongRecordField____________,
41+
)) {
42+
;
43+
}
44+
>>> Split single-element named record.
45+
if (obj case (longFieldName: longRecordFieldValue)) {;}
46+
<<<
47+
if (obj case (
48+
longFieldName: longRecordFieldValue,
49+
)) {
50+
;
51+
}
52+
>>> Split single-element named record at name.
53+
if (obj case (longFieldName: veryLongRecordFieldValue)) {;}
54+
<<<
55+
if (obj case (
56+
longFieldName: veryLongRecordFieldValue,
57+
)) {
58+
;
59+
}
60+
>>> Split single-element record with inferred name.
61+
if (obj case (:var veryLongInferredFieldName_____)) {;}
62+
<<<
63+
if (obj case (
64+
:var veryLongInferredFieldName_____,
65+
)) {
66+
;
67+
}
68+
>>> Split multiple-element record with inferred names.
69+
if (obj case (:var firstLongInferredFieldName, :var secondLongInferredName)) {;}
70+
<<<
71+
if (obj case (
72+
:var firstLongInferredFieldName,
73+
:var secondLongInferredName,
74+
)) {
75+
;
76+
}
77+
>>> Don't split between name and list subpattern.
78+
if (obj case (longFieldName: [first, second, third])) {;}
79+
<<<
80+
if (obj case (
81+
longFieldName: [first, second, third],
82+
)) {
83+
;
84+
}
85+
>>> Don't split between name and map subpattern.
86+
if (obj case (longFieldName: {first: 1, second: 2})) {;}
87+
<<<
88+
if (obj case (
89+
longFieldName: {first: 1, second: 2},
90+
)) {
91+
;
92+
}
93+
>>> Don't split between name and record subpattern.
94+
if (obj case (longFieldName: (first: 1, second: 2))) {;}
95+
<<<
96+
if (obj case (
97+
longFieldName: (first: 1, second: 2),
98+
)) {
99+
;
100+
}
101+
>>> If any field splits, all fields split.
102+
if (obj case (first, second, third, fourth, fifth)) {;}
103+
<<<
104+
if (obj case (
105+
first,
106+
second,
107+
third,
108+
fourth,
109+
fifth,
110+
)) {
111+
;
112+
}
113+
>>> Don't force outer record to split.
114+
if (obj case ((a,), (b, c))) {;}
115+
<<<
116+
if (obj case ((a,), (b, c))) {
117+
;
118+
}
119+
>>> Split nested record.
120+
if (obj case (first, (second, third, fourth), fifth, (sixth, seventh, eighth, nine, tenth,
121+
eleventh))) {;}
122+
<<<
123+
if (obj case (
124+
first,
125+
(second, third, fourth),
126+
fifth,
127+
(
128+
sixth,
129+
seventh,
130+
eighth,
131+
nine,
132+
tenth,
133+
eleventh,
134+
),
135+
)) {
136+
;
137+
}
138+
>>> Tall splitting style with line comment.
139+
if (obj case (
140+
// yeah
141+
a,b,c,
142+
d,e,f,
143+
)) {;}
144+
<<<
145+
if (obj case (
146+
// yeah
147+
a,
148+
b,
149+
c,
150+
d,
151+
e,
152+
f,
153+
)) {
154+
;
155+
}
156+
>>> Remove comma from multiple-field record pattern if unsplit
157+
if (e case (a, b,)) {}
158+
<<<
159+
if (e case (a, b)) {}
160+
>>> Add comma to record pattern if split.
161+
if (e case (longPattern1, veryLongPattern2)) {}
162+
<<<
163+
if (e case (
164+
longPattern1,
165+
veryLongPattern2,
166+
)) {}

test/pattern/record_comment.stmt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
40 columns |
2+
>>> Empty record pattern block comment.
3+
if (obj case ( /* comment */ )) {;}
4+
<<<
5+
if (obj case (/* comment */)) {
6+
;
7+
}
8+
>>> Empty record pattern line comment.
9+
if (obj case ( // comment
10+
)) {;}
11+
<<<
12+
if (obj case (
13+
// comment
14+
)) {
15+
;
16+
}
17+
>>> Record line comment between fields.
18+
if (obj case ( first , // comment
19+
second)){;}
20+
<<<
21+
if (obj case (
22+
first, // comment
23+
second,
24+
)) {
25+
;
26+
}

0 commit comments

Comments
 (0)