@@ -1883,24 +1883,27 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1883
1883
1884
1884
// If the rhs starts with a parenthesized expression, stack indentation around it.
1885
1885
// Otherwise, use regular continuation breaks.
1886
- if let ( unindentingNode, _, breakKind) = stackedIndentationBehavior ( after: binOp, rhs: rhs)
1886
+ if let ( unindentingNode, _, breakKind, _) =
1887
+ stackedIndentationBehavior ( after: binOp, rhs: rhs)
1887
1888
{
1888
1889
beforeTokens = [ . break( . open( kind: breakKind) ) ]
1889
- after ( unindentingNode. lastToken ( viewMode: . sourceAccurate) , tokens: [ . break( . close( mustBreak: false ) , size: 0 ) ] )
1890
+ after (
1891
+ unindentingNode. lastToken ( viewMode: . sourceAccurate) ,
1892
+ tokens: [ . break( . close( mustBreak: false ) , size: 0 ) ] )
1890
1893
} else {
1891
1894
beforeTokens = [ . break( . continue) ]
1892
1895
}
1893
1896
1894
1897
// When the RHS is a simple expression, even if is requires multiple lines, we don't add a
1895
1898
// group so that as much of the expression as possible can stay on the same line as the
1896
1899
// operator token.
1897
- if isCompoundExpression ( rhs) {
1900
+ if isCompoundExpression ( rhs) && leftmostMultilineStringLiteral ( of : rhs ) == nil {
1898
1901
beforeTokens. append ( . open)
1899
1902
after ( rhs. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
1900
1903
}
1901
1904
1902
1905
after ( binOp. lastToken ( viewMode: . sourceAccurate) , tokens: beforeTokens)
1903
- } else if let ( unindentingNode, shouldReset, breakKind) =
1906
+ } else if let ( unindentingNode, shouldReset, breakKind, shouldGroup ) =
1904
1907
stackedIndentationBehavior ( after: binOp, rhs: rhs)
1905
1908
{
1906
1909
// For parenthesized expressions and for unparenthesized usages of `&&` and `||`, we don't
@@ -1910,16 +1913,22 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1910
1913
// use open-continuation/close pairs around such operators and their right-hand sides so
1911
1914
// that the continuation breaks inside those scopes "stack", instead of receiving the
1912
1915
// usual single-level "continuation line or not" behavior.
1913
- let openBreakTokens : [ Token ] = [ . break( . open( kind: breakKind) ) , . open]
1916
+ var openBreakTokens : [ Token ] = [ . break( . open( kind: breakKind) ) ]
1917
+ if shouldGroup {
1918
+ openBreakTokens. append ( . open)
1919
+ }
1914
1920
if wrapsBeforeOperator {
1915
1921
before ( binOp. firstToken ( viewMode: . sourceAccurate) , tokens: openBreakTokens)
1916
1922
} else {
1917
1923
after ( binOp. lastToken ( viewMode: . sourceAccurate) , tokens: openBreakTokens)
1918
1924
}
1919
1925
1920
- let closeBreakTokens : [ Token ] =
1926
+ var closeBreakTokens : [ Token ] =
1921
1927
( shouldReset ? [ . break( . reset, size: 0 ) ] : [ ] )
1922
- + [ . break( . close( mustBreak: false ) , size: 0 ) , . close]
1928
+ + [ . break( . close( mustBreak: false ) , size: 0 ) ]
1929
+ if shouldGroup {
1930
+ closeBreakTokens. append ( . close)
1931
+ }
1923
1932
after ( unindentingNode. lastToken ( viewMode: . sourceAccurate) , tokens: closeBreakTokens)
1924
1933
} else {
1925
1934
if wrapsBeforeOperator {
@@ -2031,7 +2040,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2031
2040
if let initializer = node. initializer {
2032
2041
let expr = initializer. value
2033
2042
2034
- if let ( unindentingNode, _, breakKind) = stackedIndentationBehavior ( rhs: expr) {
2043
+ if let ( unindentingNode, _, breakKind, _ ) = stackedIndentationBehavior ( rhs: expr) {
2035
2044
after ( initializer. equal, tokens: . break( . open( kind: breakKind) ) )
2036
2045
after ( unindentingNode. lastToken ( viewMode: . sourceAccurate) , tokens: . break( . close( mustBreak: false ) , size: 0 ) )
2037
2046
} else {
@@ -2042,7 +2051,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2042
2051
// When the RHS is a simple expression, even if is requires multiple lines, we don't add a
2043
2052
// group so that as much of the expression as possible can stay on the same line as the
2044
2053
// operator token.
2045
- if isCompoundExpression ( expr) {
2054
+ if isCompoundExpression ( expr) && leftmostMultilineStringLiteral ( of : expr ) == nil {
2046
2055
before ( expr. firstToken ( viewMode: . sourceAccurate) , tokens: . open)
2047
2056
after ( expr. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
2048
2057
}
@@ -3357,8 +3366,9 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3357
3366
}
3358
3367
3359
3368
/// Determines if indentation should be stacked around a subexpression to the right of the given
3360
- /// operator, and, if so, returns the node after which indentation stacking should be closed and
3361
- /// whether or not the continuation state should be reset as well.
3369
+ /// operator, and, if so, returns the node after which indentation stacking should be closed,
3370
+ /// whether or not the continuation state should be reset as well, and whether or not a group
3371
+ /// should be placed around the operator and the expression.
3362
3372
///
3363
3373
/// Stacking is applied around parenthesized expressions, but also for low-precedence operators
3364
3374
/// that frequently occur in long chains, such as logical AND (`&&`) and OR (`||`) in conditional
@@ -3367,7 +3377,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3367
3377
private func stackedIndentationBehavior(
3368
3378
after operatorExpr: ExprSyntax ? = nil ,
3369
3379
rhs: ExprSyntax
3370
- ) -> ( unindentingNode: Syntax , shouldReset: Bool , breakKind: OpenBreakKind ) ? {
3380
+ ) -> ( unindentingNode: Syntax , shouldReset: Bool , breakKind: OpenBreakKind , shouldGroup : Bool ) ? {
3371
3381
// Check for logical operators first, and if it's that kind of operator, stack indentation
3372
3382
// around the entire right-hand-side. We have to do this check before checking the RHS for
3373
3383
// parentheses because if the user writes something like `... && (foo) > bar || ...`, we don't
@@ -3387,9 +3397,18 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3387
3397
// the paren to the last token of `rhs`.
3388
3398
if let unindentingParenExpr = outermostEnclosingNode ( from: Syntax ( rhs) ) {
3389
3399
return (
3390
- unindentingNode: unindentingParenExpr, shouldReset: true , breakKind: . continuation)
3400
+ unindentingNode: unindentingParenExpr,
3401
+ shouldReset: true ,
3402
+ breakKind: . continuation,
3403
+ shouldGroup: true
3404
+ )
3391
3405
}
3392
- return ( unindentingNode: Syntax ( rhs) , shouldReset: true , breakKind: . continuation)
3406
+ return (
3407
+ unindentingNode: Syntax ( rhs) ,
3408
+ shouldReset: true ,
3409
+ breakKind: . continuation,
3410
+ shouldGroup: true
3411
+ )
3393
3412
}
3394
3413
}
3395
3414
@@ -3399,8 +3418,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3399
3418
// We don't try to absorb any parens in this case, because the condition of a ternary cannot
3400
3419
// be grouped with any exprs outside of the condition.
3401
3420
return (
3402
- unindentingNode: Syntax ( ternaryExpr. conditionExpression) , shouldReset: false ,
3403
- breakKind: . continuation)
3421
+ unindentingNode: Syntax ( ternaryExpr. conditionExpression) ,
3422
+ shouldReset: false ,
3423
+ breakKind: . continuation,
3424
+ shouldGroup: true
3425
+ )
3404
3426
}
3405
3427
3406
3428
// If the right-hand-side of the operator is or starts with a parenthesized expression, stack
@@ -3411,7 +3433,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3411
3433
// paren into the right hand side by unindenting after the final closing paren. This glues the
3412
3434
// paren to the last token of `rhs`.
3413
3435
if let unindentingParenExpr = outermostEnclosingNode ( from: Syntax ( rhs) ) {
3414
- return ( unindentingNode: unindentingParenExpr, shouldReset: true , breakKind: . continuation)
3436
+ return (
3437
+ unindentingNode: unindentingParenExpr,
3438
+ shouldReset: true ,
3439
+ breakKind: . continuation,
3440
+ shouldGroup: true
3441
+ )
3415
3442
}
3416
3443
3417
3444
if let innerExpr = parenthesizedExpr. elementList. first? . expression,
@@ -3423,14 +3450,23 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
3423
3450
}
3424
3451
3425
3452
return (
3426
- unindentingNode: Syntax ( parenthesizedExpr) , shouldReset: false , breakKind: . continuation)
3453
+ unindentingNode: Syntax ( parenthesizedExpr) ,
3454
+ shouldReset: false ,
3455
+ breakKind: . continuation,
3456
+ shouldGroup: true
3457
+ )
3427
3458
}
3428
3459
3429
3460
// If the expression is a multiline string that is unparenthesized, create a block-based
3430
3461
// indentation scope and have the segments aligned inside it.
3431
3462
if let stringLiteralExpr = leftmostMultilineStringLiteral ( of: rhs) {
3432
3463
pendingMultilineStringBreakKinds [ stringLiteralExpr] = . same
3433
- return ( unindentingNode: Syntax ( stringLiteralExpr) , shouldReset: false , breakKind: . block)
3464
+ return (
3465
+ unindentingNode: Syntax ( stringLiteralExpr) ,
3466
+ shouldReset: false ,
3467
+ breakKind: . block,
3468
+ shouldGroup: false
3469
+ )
3434
3470
}
3435
3471
3436
3472
// Otherwise, don't stack--use regular continuation breaks instead.
0 commit comments