@@ -519,7 +519,24 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
519
519
520
520
override func visit( _ node: ForInStmtSyntax ) -> SyntaxVisitorContinueKind {
521
521
after ( node. labelColon, tokens: . space)
522
- after ( node. forKeyword, tokens: . space)
522
+
523
+ // If we have a `(try) await` clause, allow breaking after the `for` so that the `(try) await`
524
+ // can fall onto the next line if needed, and if both `try await` are present, keep them
525
+ // together. Otherwise, keep `for` glued to the token after it so that we break somewhere later
526
+ // on the line.
527
+ if let awaitKeyword = node. awaitKeyword {
528
+ after ( node. forKeyword, tokens: . break)
529
+ if let tryKeyword = node. tryKeyword {
530
+ before ( tryKeyword, tokens: . open)
531
+ after ( tryKeyword, tokens: . break)
532
+ after ( awaitKeyword, tokens: . close, . break)
533
+ } else {
534
+ after ( awaitKeyword, tokens: . break)
535
+ }
536
+ } else {
537
+ after ( node. forKeyword, tokens: . space)
538
+ }
539
+
523
540
after ( node. caseKeyword, tokens: . space)
524
541
before ( node. inKeyword, tokens: . break)
525
542
after ( node. inKeyword, tokens: . space)
@@ -897,10 +914,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
897
914
898
915
if let calledMemberAccessExpr = node. calledExpression. as ( MemberAccessExprSyntax . self) {
899
916
if let base = calledMemberAccessExpr. base, base. is ( IdentifierExprSyntax . self) {
900
- // When this function call is wrapped by a try-expr, the group applied when visiting the
901
- // try-expr is sufficient. Adding another gruop here in that case can result in
902
- // unnecessarily breaking after the try keyword.
903
- if !( base. firstToken? . previousToken? . parent? . is ( TryExprSyntax . self) ?? false ) {
917
+ // When this function call is wrapped by a try-expr or await-expr, the group applied when
918
+ // visiting that wrapping expression is sufficient. Adding another group here in that case
919
+ // can result in unnecessarily breaking after the try/await keyword.
920
+ if !( base. firstToken? . previousToken? . parent? . is ( TryExprSyntax . self) ?? false
921
+ || base. firstToken? . previousToken? . parent? . is ( AwaitExprSyntax . self) ?? false ) {
904
922
before ( base. firstToken, tokens: . open)
905
923
after ( calledMemberAccessExpr. name. lastToken, tokens: . close)
906
924
}
@@ -1087,7 +1105,13 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1087
1105
}
1088
1106
}
1089
1107
1108
+ before ( node. asyncKeyword, tokens: . break)
1090
1109
before ( node. throwsTok, tokens: . break)
1110
+ if let asyncKeyword = node. asyncKeyword, let throwsTok = node. throwsTok {
1111
+ before ( asyncKeyword, tokens: . open)
1112
+ after ( throwsTok, tokens: . close)
1113
+ }
1114
+
1091
1115
before ( node. output? . arrow, tokens: . break)
1092
1116
after ( node. lastToken, tokens: . close)
1093
1117
before ( node. inTok, tokens: . break( . same) )
@@ -1461,32 +1485,52 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1461
1485
tokens: . break( . continue, newlines: . elective( ignoresDiscretionary: true ) ) )
1462
1486
1463
1487
// Check for an anchor token inside of the expression to group with the try keyword.
1464
- if let anchorToken = findTryExprConnectingToken ( inExpr: node. expression) {
1488
+ if let anchorToken = findTryAwaitExprConnectingToken ( inExpr: node. expression) {
1465
1489
before ( node. tryKeyword, tokens: . open)
1466
1490
after ( anchorToken, tokens: . close)
1467
1491
}
1468
1492
1469
1493
return . visitChildren
1470
1494
}
1471
1495
1496
+ override func visit( _ node: AwaitExprSyntax ) -> SyntaxVisitorContinueKind {
1497
+ before (
1498
+ node. expression. firstToken,
1499
+ tokens: . break( . continue, newlines: . elective( ignoresDiscretionary: true ) ) )
1500
+
1501
+ // Check for an anchor token inside of the expression to group with the await keyword.
1502
+ if !( node. parent? . is ( TryExprSyntax . self) ?? false ) ,
1503
+ let anchorToken = findTryAwaitExprConnectingToken ( inExpr: node. expression)
1504
+ {
1505
+ before ( node. awaitKeyword, tokens: . open)
1506
+ after ( anchorToken, tokens: . close)
1507
+ }
1508
+
1509
+ return . visitChildren
1510
+ }
1511
+
1472
1512
/// Searches the AST from `expr` to find a token that should be grouped with an enclosing
1473
- /// try-expr. Returns that token, or nil when no such token is found.
1513
+ /// try-expr or await-expr . Returns that token, or nil when no such token is found.
1474
1514
///
1475
- /// - Parameter expr: An expression that is wrapped by a try-expr.
1476
- /// - Returns: A token that should be grouped with the try-expr, or nil.
1477
- func findTryExprConnectingToken( inExpr expr: ExprSyntax ) -> TokenSyntax ? {
1515
+ /// - Parameter expr: An expression that is wrapped by a try-expr or await-expr.
1516
+ /// - Returns: A token that should be grouped with the try-expr or await-expr, or nil.
1517
+ func findTryAwaitExprConnectingToken( inExpr expr: ExprSyntax ) -> TokenSyntax ? {
1518
+ if let awaitExpr = expr. as ( AwaitExprSyntax . self) {
1519
+ // If we were called from the `try` of a `try await <expr>`, drill into the child expression.
1520
+ return findTryAwaitExprConnectingToken ( inExpr: awaitExpr. expression)
1521
+ }
1478
1522
if let callingExpr = expr. asProtocol ( CallingExprSyntaxProtocol . self) {
1479
- return findTryExprConnectingToken ( inExpr: callingExpr. calledExpression)
1523
+ return findTryAwaitExprConnectingToken ( inExpr: callingExpr. calledExpression)
1480
1524
}
1481
1525
if let memberAccessExpr = expr. as ( MemberAccessExprSyntax . self) , let base = memberAccessExpr. base
1482
1526
{
1483
- // When there's a simple base (i.e. identifier), group the entire `try <base>.<name>`
1527
+ // When there's a simple base (i.e. identifier), group the entire `try/await <base>.<name>`
1484
1528
// sequence. This check has to happen here so that the `MemberAccessExprSyntax.name` is
1485
1529
// available.
1486
1530
if base. is ( IdentifierExprSyntax . self) {
1487
1531
return memberAccessExpr. name. lastToken
1488
1532
}
1489
- return findTryExprConnectingToken ( inExpr: base)
1533
+ return findTryAwaitExprConnectingToken ( inExpr: base)
1490
1534
}
1491
1535
if expr. is ( IdentifierExprSyntax . self) {
1492
1536
return expr. lastToken
@@ -1634,13 +1678,28 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1634
1678
}
1635
1679
1636
1680
override func visit( _ node: DeclModifierSyntax ) -> SyntaxVisitorContinueKind {
1637
- after ( node. lastToken, tokens: . break)
1681
+ // Due to the way we currently use spaces after let/var keywords in variable bindings, we need
1682
+ // this special exception for `async let` statements to avoid breaking prematurely between the
1683
+ // `async` and `let` keywords.
1684
+ let breakOrSpace : Token
1685
+ if node. name. tokenKind == . identifier( " async " ) {
1686
+ breakOrSpace = . space
1687
+ } else {
1688
+ breakOrSpace = . break
1689
+ }
1690
+ after ( node. lastToken, tokens: breakOrSpace)
1638
1691
return . visitChildren
1639
1692
}
1640
1693
1641
1694
override func visit( _ node: FunctionSignatureSyntax ) -> SyntaxVisitorContinueKind {
1642
1695
before ( node. asyncOrReasyncKeyword, tokens: . break)
1643
1696
before ( node. throwsOrRethrowsKeyword, tokens: . break)
1697
+ if let asyncOrReasyncKeyword = node. asyncOrReasyncKeyword,
1698
+ let throwsOrRethrowsKeyword = node. throwsOrRethrowsKeyword
1699
+ {
1700
+ before ( asyncOrReasyncKeyword, tokens: . open)
1701
+ after ( throwsOrRethrowsKeyword, tokens: . close)
1702
+ }
1644
1703
before ( node. output? . firstToken, tokens: . break)
1645
1704
return . visitChildren
1646
1705
}
@@ -3087,10 +3146,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3087
3146
}
3088
3147
3089
3148
/// Returns whether the given expression consists of multiple subexpressions. Certain expressions
3090
- /// that are known to wrap an expressions , e.g. try expressions, are handled by checking the
3149
+ /// that are known to wrap an expression , e.g. try expressions, are handled by checking the
3091
3150
/// expression that they contain.
3092
3151
private func isCompoundExpression( _ expr: ExprSyntax ) -> Bool {
3093
3152
switch Syntax ( expr) . as ( SyntaxEnum . self) {
3153
+ case . awaitExpr( let awaitExpr) :
3154
+ return isCompoundExpression ( awaitExpr. expression)
3094
3155
case . sequenceExpr( let sequenceExpr) :
3095
3156
return sequenceExpr. elements. count > 1
3096
3157
case . ternaryExpr:
0 commit comments