@@ -1460,7 +1460,7 @@ private final class TokenStreamCreator: SyntaxVisitor {
1460
1460
guard let node = node, let contentsKeyPath = contentsKeyPath else { return }
1461
1461
1462
1462
if shouldResetBeforeLeftBrace {
1463
- before ( node. leftBrace, tokens: . break( . reset, size: 1 ) )
1463
+ before ( node. leftBrace, tokens: . break( . reset, size: 1 , ignoresDiscretionary : true ) )
1464
1464
}
1465
1465
if !areBracesCompletelyEmpty( node, contentsKeyPath: contentsKeyPath) {
1466
1466
after ( node. leftBrace, tokens: . break( . open, size: 1 ) , . open)
@@ -1626,17 +1626,25 @@ private final class TokenStreamCreator: SyntaxVisitor {
1626
1626
/// Returns a value indicating whether or not discretionary newlines are permitted before the
1627
1627
/// given syntax token.
1628
1628
///
1629
- /// Discretionary newlines are allowed before any token that is preceded by a break or an existing
1630
- /// newline (ignoring open/close group tokens, which do not contribute to this). In other words,
1631
- /// this means that users may insert their own breaks in places where the pretty printer allows
1632
- /// them, even if those breaks wouldn't cause wrapping based on the column limit, but they may not
1633
- /// place them in places where the pretty printer would not break (for example, at a space token
1634
- /// that is intended to keep two tokens glued together).
1629
+ /// Discretionary newlines are allowed before any token (ignoring open/close group tokens, which
1630
+ /// do not contribute to this) that is preceded by an existing newline or that is preceded by a
1631
+ /// break whose `ignoresDiscretionary` property is false. In other words, this means that users
1632
+ /// may insert their own breaks in places where the pretty printer allows them, even if those
1633
+ /// breaks wouldn't cause wrapping based on the column limit, but they may not place them in
1634
+ /// places where the pretty printer would not break (for example, at a space token that is
1635
+ /// intended to keep two tokens glued together).
1636
+ ///
1637
+ /// Furthermore, breaks with `ignoresDiscretionary` equal to `true` are in effect "last resort"
1638
+ /// breaks; a user's newline will be discarded unless the algorithm *must* break there. For
1639
+ /// example, an open curly brace on a non-continuation line should always be kept on the same line
1640
+ /// as the tokens before it unless the tokens before it are exactly the length of the line and a
1641
+ /// break must be inserted there to prevent the brace from going over the limit.
1635
1642
private func isDiscretionaryNewlineAllowed( before token: TokenSyntax ) -> Bool {
1636
1643
func isBreakMoreRecentThanNonbreakingContent( _ tokens: [ Token ] ) -> Bool ? {
1637
1644
for token in tokens. reversed ( ) as ReversedCollection {
1638
1645
switch token {
1639
- case . break, . newlines: return true
1646
+ case . newlines: return true
1647
+ case . break( _, _, let ignoresDiscretionary) : return !ignoresDiscretionary
1640
1648
case . comment, . space, . syntax, . verbatim: return false
1641
1649
default : break
1642
1650
}
0 commit comments