Skip to content

Commit f043022

Browse files
authored
Format conditional expressions. (#1292)
Format conditional expressions.
1 parent 15fef68 commit f043022

File tree

5 files changed

+176
-3
lines changed

5 files changed

+176
-3
lines changed

lib/src/front_end/ast_node_visitor.dart

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:analyzer/source/line_info.dart';
88
import '../dart_formatter.dart';
99
import '../piece/do_while.dart';
1010
import '../piece/if.dart';
11+
import '../piece/infix.dart';
1112
import '../piece/piece.dart';
1213
import '../piece/variable.dart';
1314
import '../source_code.dart';
@@ -210,7 +211,32 @@ class AstNodeVisitor extends ThrowingAstVisitor<void>
210211

211212
@override
212213
void visitConditionalExpression(ConditionalExpression node) {
213-
throw UnimplementedError();
214+
visit(node.condition);
215+
var condition = writer.pop();
216+
writer.split();
217+
218+
token(node.question);
219+
writer.space();
220+
visit(node.thenExpression);
221+
var thenBranch = writer.pop();
222+
writer.split();
223+
224+
token(node.colon);
225+
writer.space();
226+
visit(node.elseExpression);
227+
var elseBranch = writer.pop();
228+
229+
var piece = InfixPiece([condition, thenBranch, elseBranch]);
230+
231+
// If conditional expressions are directly nested, force them all to split,
232+
// both parents and children.
233+
if (node.parent is ConditionalExpression ||
234+
node.thenExpression is ConditionalExpression ||
235+
node.elseExpression is ConditionalExpression) {
236+
piece.pin(State.split);
237+
}
238+
239+
writer.push(piece);
214240
}
215241

216242
@override

lib/src/piece/assign.dart

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import 'piece.dart';
3434
///
3535
/// ```
3636
/// var name =
37-
/// longValueExpression;
37+
/// longValueExpression;
3838
/// ```
3939
class AssignPiece extends Piece {
4040
/// Split inside the value but not at the `=`.
@@ -59,6 +59,30 @@ class AssignPiece extends Piece {
5959
AssignPiece(this.target, this.value, {required bool isValueDelimited})
6060
: _isValueDelimited = isValueDelimited;
6161

62+
// TODO(tall): The old formatter allows the first operand of a split
63+
// conditional expression to be on the same line as the `=`, as in:
64+
//
65+
// ```
66+
// var value = condition
67+
// ? thenValue
68+
// : elseValue;
69+
// ```
70+
//
71+
// It's not clear if this behavior is deliberate or not. It does look OK,
72+
// though. We could do the same thing here. If we do, I think it's worth
73+
// considering allowing the same thing for infix expressions too:
74+
//
75+
// ```
76+
// var value = operand +
77+
// operand +
78+
// operand;
79+
// ```
80+
//
81+
// For now, we not implement this special case behavior. Once more of the
82+
// language is implemented in the new back end and we can run the formatter
83+
// on a large corpus of code, we can try it out and see if the special case
84+
// behavior is worth it.
85+
6286
@override
6387
List<State> get additionalStates =>
6488
[if (_isValueDelimited) _insideValue, _atEquals];

test/expression/condition.stmt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
40 columns |
2+
>>> Unsplit.
3+
condition ? thenBranch : elseBranch ;
4+
<<<
5+
condition ? thenBranch : elseBranch;
6+
>>> Split because condition splits.
7+
veryLongElement != otherReallyLongElement ? longArgument : arg;
8+
<<<
9+
veryLongElement !=
10+
otherReallyLongElement
11+
? longArgument
12+
: arg;
13+
>>> Split because of split in then branch.
14+
condition ? veryLongExpression +
15+
otherLongExpression : elseExpr;
16+
<<<
17+
condition
18+
? veryLongExpression +
19+
otherLongExpression
20+
: elseExpr;
21+
>>> Split because of split in else branch.
22+
condition ? thenExpression
23+
: veryLongExpression +
24+
otherLongExpression;
25+
<<<
26+
condition
27+
? thenExpression
28+
: veryLongExpression +
29+
otherLongExpression;
30+
>>> Force split all conditionals when nested.
31+
var kind = a ? b ? c : d : e;
32+
<<<
33+
var kind =
34+
a
35+
? b
36+
? c
37+
: d
38+
: e;
39+
>>>
40+
var kind = a ? b : c ? d : e;
41+
<<<
42+
var kind =
43+
a
44+
? b
45+
: c
46+
? d
47+
: e;
48+
>>> Don't force split conditionals when indirectly nested.
49+
var kind = a ? b : (c ? d : e);
50+
<<<
51+
var kind = a ? b : (c ? d : e);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
40 columns |
2+
>>> Inline block comment before `?`.
3+
cond /* c */ ? 1 : 2;
4+
<<<
5+
cond /* c */ ? 1 : 2;
6+
>>> Inline block comment after `?`.
7+
cond ? /* c */ 1 : 2;
8+
<<<
9+
cond ? /* c */ 1 : 2;
10+
>>> Inline block comment before `:`.
11+
cond ? 1 /* c */ : 2;
12+
<<<
13+
cond ? 1 /* c */ : 2;
14+
>>> Inline block comment after `:`.
15+
cond ? 1 : /* c */ 2;
16+
<<<
17+
cond ? 1 : /* c */ 2;
18+
>>> Inline block comment after else.
19+
cond ? 1 : 2 /* c */;
20+
<<<
21+
cond ? 1 : 2 /* c */;
22+
>>> Line comment before `?`.
23+
cond // c
24+
? 1 : 2;
25+
<<<
26+
cond // c
27+
? 1
28+
: 2;
29+
>>> Line comment after `?`.
30+
cond ? // c
31+
1 : 2;
32+
<<<
33+
### Looks weird, but users generally won't put comments here.
34+
cond
35+
? // c
36+
1
37+
: 2;
38+
>>> Line comment before `:`.
39+
cond ? 1 // c
40+
: 2;
41+
<<<
42+
cond
43+
? 1 // c
44+
: 2;
45+
>>> Line comment after `:`.
46+
cond ? 1 : // c
47+
2;
48+
<<<
49+
### Looks weird, but users generally won't put comments here.
50+
cond
51+
? 1
52+
: // c
53+
2;
54+
>>> Line comment after else.
55+
cond ? 1 : 2 // c
56+
;
57+
<<<
58+
### Looks weird, but users generally won't put comments here.
59+
cond
60+
? 1
61+
: 2 // c
62+
;

test/statement/variable.stmt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,14 @@ var variableName = ([
193193
var variableName = (notDelimited + expression);
194194
<<<
195195
var variableName =
196-
(notDelimited + expression);
196+
(notDelimited + expression);
197+
>>> Split all variables if an initializer has a split internally.
198+
var a = 1, b = [element, element, element, element];
199+
<<<
200+
var a = 1,
201+
b = [
202+
element,
203+
element,
204+
element,
205+
element,
206+
];

0 commit comments

Comments
 (0)