@@ -359,11 +359,10 @@ class SourceVisitor extends ThrowingAstVisitor {
359
359
// appears before the first operand.
360
360
builder.startLazyRule ();
361
361
362
- // Flatten out a tree/chain of the same precedence. If we split on this
363
- // precedence level , we will break all of them.
362
+ // Flatten out a tree/chain of the same precedence. If we need to split on
363
+ // any of them , we split on all of them.
364
364
var precedence = node.operator .type.precedence;
365
365
366
- @override
367
366
void traverse (Expression e) {
368
367
if (e is BinaryExpression && e.operator .type.precedence == precedence) {
369
368
traverse (e.leftOperand);
@@ -391,6 +390,46 @@ class SourceVisitor extends ThrowingAstVisitor {
391
390
builder.endRule ();
392
391
}
393
392
393
+ @override
394
+ void visitBinaryPattern (BinaryPattern node) {
395
+ builder.startSpan ();
396
+ builder.nestExpression (now: true );
397
+
398
+ // Start lazily so we don't force the operator to split if a line comment
399
+ // appears before the first operand.
400
+ builder.startLazyRule ();
401
+
402
+ // Flatten out a tree/chain of the same precedence. If we need to split on
403
+ // any of them, we split on all of them.
404
+ var precedence = node.operator .type.precedence;
405
+
406
+ void traverse (DartPattern p) {
407
+ if (p is BinaryPattern && p.operator .type.precedence == precedence) {
408
+ traverse (p.leftOperand);
409
+
410
+ space ();
411
+ token (p.operator );
412
+
413
+ split ();
414
+ traverse (p.rightOperand);
415
+ } else {
416
+ visit (p);
417
+ }
418
+ }
419
+
420
+ // Blocks as operands to infix patterns should always nest like regular
421
+ // operands.
422
+ builder.startBlockArgumentNesting ();
423
+
424
+ traverse (node);
425
+
426
+ builder.endBlockArgumentNesting ();
427
+
428
+ builder.unnest ();
429
+ builder.endSpan ();
430
+ builder.endRule ();
431
+ }
432
+
394
433
@override
395
434
void visitBlock (Block node) {
396
435
// Treat empty blocks specially. In most cases, they are not allowed to
@@ -755,6 +794,12 @@ class SourceVisitor extends ThrowingAstVisitor {
755
794
visit (node.uri);
756
795
}
757
796
797
+ @override
798
+ void visitConstantPattern (ConstantPattern node) {
799
+ token (node.constKeyword, after: space);
800
+ visit (node.expression);
801
+ }
802
+
758
803
@override
759
804
void visitConstructorDeclaration (ConstructorDeclaration node) {
760
805
visitMetadata (node.metadata);
@@ -1774,12 +1819,8 @@ class SourceVisitor extends ThrowingAstVisitor {
1774
1819
1775
1820
var hasInnerControlFlow = false ;
1776
1821
for (var element in ifElements) {
1777
- // The condition.
1778
- token (element.ifKeyword);
1779
- space ();
1780
- token (element.leftParenthesis);
1781
- visit (element.condition);
1782
- token (element.rightParenthesis);
1822
+ _visitIfCondition (element.ifKeyword, element.leftParenthesis,
1823
+ element.condition, element.caseClause, element.rightParenthesis);
1783
1824
1784
1825
visitChild (element, element.thenElement);
1785
1826
if (element.thenElement.isControlFlowElement) {
@@ -1822,13 +1863,8 @@ class SourceVisitor extends ThrowingAstVisitor {
1822
1863
1823
1864
@override
1824
1865
void visitIfStatement (IfStatement node) {
1825
- builder.nestExpression ();
1826
- token (node.ifKeyword);
1827
- space ();
1828
- token (node.leftParenthesis);
1829
- visit (node.condition);
1830
- token (node.rightParenthesis);
1831
- builder.unnest ();
1866
+ _visitIfCondition (node.ifKeyword, node.leftParenthesis, node.condition,
1867
+ node.caseClause, node.rightParenthesis);
1832
1868
1833
1869
void visitClause (Statement clause) {
1834
1870
if (clause is Block || clause is IfStatement ) {
@@ -2222,6 +2258,15 @@ class SourceVisitor extends ThrowingAstVisitor {
2222
2258
token (node.rightParenthesis);
2223
2259
}
2224
2260
2261
+ @override
2262
+ void visitParenthesizedPattern (ParenthesizedPattern node) {
2263
+ builder.nestExpression ();
2264
+ token (node.leftParenthesis);
2265
+ visit (node.pattern);
2266
+ builder.unnest ();
2267
+ token (node.rightParenthesis);
2268
+ }
2269
+
2225
2270
@override
2226
2271
void visitPartDirective (PartDirective node) {
2227
2272
_visitDirectiveMetadata (node);
@@ -2402,6 +2447,13 @@ class SourceVisitor extends ThrowingAstVisitor {
2402
2447
});
2403
2448
}
2404
2449
2450
+ @override
2451
+ void visitRelationalPattern (RelationalPattern node) {
2452
+ token (node.operator );
2453
+ space ();
2454
+ visit (node.operand);
2455
+ }
2456
+
2405
2457
@override
2406
2458
void visitRethrowExpression (RethrowExpression node) {
2407
2459
token (node.rethrowKeyword);
@@ -2538,7 +2590,6 @@ class SourceVisitor extends ThrowingAstVisitor {
2538
2590
token (node.colon);
2539
2591
2540
2592
builder.indent ();
2541
- // TODO(rnystrom): Allow inline cases?
2542
2593
newline ();
2543
2594
2544
2595
visitNodes (node.statements, between: oneOrTwoNewlines);
@@ -2552,7 +2603,29 @@ class SourceVisitor extends ThrowingAstVisitor {
2552
2603
token (node.colon);
2553
2604
2554
2605
builder.indent ();
2555
- // TODO(rnystrom): Allow inline cases?
2606
+ newline ();
2607
+
2608
+ visitNodes (node.statements, between: oneOrTwoNewlines);
2609
+ builder.unindent ();
2610
+ }
2611
+
2612
+ @override
2613
+ void visitSwitchPatternCase (SwitchPatternCase node) {
2614
+ _visitLabels (node.labels);
2615
+
2616
+ token (node.keyword);
2617
+ space ();
2618
+
2619
+ builder.startBlockArgumentNesting ();
2620
+ builder.nestExpression ();
2621
+ visit (node.guardedPattern.pattern);
2622
+ builder.unnest ();
2623
+ builder.endBlockArgumentNesting ();
2624
+
2625
+ visit (node.guardedPattern.whenClause);
2626
+ token (node.colon);
2627
+
2628
+ builder.indent ();
2556
2629
newline ();
2557
2630
2558
2631
visitNodes (node.statements, between: oneOrTwoNewlines);
@@ -2711,6 +2784,20 @@ class SourceVisitor extends ThrowingAstVisitor {
2711
2784
});
2712
2785
}
2713
2786
2787
+ @override
2788
+ void visitWhenClause (WhenClause node) {
2789
+ builder.startRule ();
2790
+ split ();
2791
+ token (node.whenKeyword);
2792
+ space ();
2793
+ builder.startBlockArgumentNesting ();
2794
+ builder.nestExpression ();
2795
+ visit (node.expression);
2796
+ builder.unnest ();
2797
+ builder.endBlockArgumentNesting ();
2798
+ builder.endRule ();
2799
+ }
2800
+
2714
2801
@override
2715
2802
void visitWhileStatement (WhileStatement node) {
2716
2803
builder.nestExpression ();
@@ -3330,6 +3417,45 @@ class SourceVisitor extends ThrowingAstVisitor {
3330
3417
builder.endRule ();
3331
3418
}
3332
3419
3420
+ /// Visits the `if (<expr> [case <pattern> [when <expr>]])` header of an if
3421
+ /// statement or element.
3422
+ void _visitIfCondition (Token ifKeyword, Token leftParenthesis,
3423
+ AstNode condition, CaseClause ? caseClause, Token rightParenthesis) {
3424
+ builder.nestExpression ();
3425
+ token (ifKeyword);
3426
+ space ();
3427
+ token (leftParenthesis);
3428
+
3429
+ if (caseClause != null ) {
3430
+ // Wrap the rule for splitting before "case" around the value expression
3431
+ // so that if the value splits, we split before "case" too.
3432
+ builder.startRule ();
3433
+
3434
+ // Nest the condition so that it indents deeper than the case clause.
3435
+ builder.nestExpression ();
3436
+ }
3437
+
3438
+ visit (condition);
3439
+
3440
+ // If-case clause.
3441
+ if (caseClause != null ) {
3442
+ split ();
3443
+ token (caseClause.caseKeyword);
3444
+ space ();
3445
+ builder.startBlockArgumentNesting ();
3446
+ builder.nestExpression ();
3447
+ visit (caseClause.guardedPattern.pattern);
3448
+ builder.unnest ();
3449
+ builder.endBlockArgumentNesting ();
3450
+ builder.endRule ();
3451
+ visit (caseClause.guardedPattern.whenClause);
3452
+ }
3453
+
3454
+ token (rightParenthesis);
3455
+ if (caseClause != null ) builder.unnest ();
3456
+ builder.unnest ();
3457
+ }
3458
+
3333
3459
/// Writes the separator between a type annotation and a variable or
3334
3460
/// parameter. If the preceding type annotation ends in a delimited list of
3335
3461
/// elements that have block formatting, then we don't split between the
0 commit comments