@@ -135,12 +135,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
135
135
}
136
136
}
137
137
138
- private func verbatimToken( _ node: Syntax ) {
138
+ private func verbatimToken( _ node: Syntax , indentingBehavior : IndentingBehavior = . allLines ) {
139
139
if let firstToken = node. firstToken {
140
140
appendBeforeTokens ( firstToken)
141
141
}
142
142
143
- appendToken ( . verbatim( Verbatim ( text: node. description, indentingBehavior: . allLines ) ) )
143
+ appendToken ( . verbatim( Verbatim ( text: node. description, indentingBehavior: indentingBehavior ) ) )
144
144
145
145
if let lastToken = node. lastToken {
146
146
// Extract any comments that trail the verbatim block since they belong to the next syntax
@@ -1769,6 +1769,24 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1769
1769
}
1770
1770
1771
1771
override func visit( _ node: InfixOperatorExprSyntax ) -> SyntaxVisitorContinueKind {
1772
+ // FIXME: This is a workaround/hack for https://github.com/apple/swift-syntax/issues/928. For
1773
+ // keypaths like `\.?.foo`, they get represented (after folding) as an infix operator expression
1774
+ // with an empty keypath, followed by the "binary operator" `.?.`, followed by other
1775
+ // expressions. We can detect this and treat the whole thing as a verbatim node, which mimics
1776
+ // what we do today for keypaths (i.e., nothing).
1777
+ if let keyPathExpr = node. leftOperand. as ( KeyPathExprSyntax . self) ,
1778
+ keyPathExpr. components. isEmpty
1779
+ {
1780
+ // If there were spaces in the trailing trivia of the previous token, they would have been
1781
+ // ignored (since this expression would be expected to insert its own preceding breaks).
1782
+ // Preserve that whitespace verbatim for now.
1783
+ if let previousToken = node. firstToken? . previousToken {
1784
+ appendTrailingTrivia ( previousToken, forced: true )
1785
+ }
1786
+ verbatimToken ( Syntax ( node) , indentingBehavior: . none)
1787
+ return . skipChildren
1788
+ }
1789
+
1772
1790
let binOp = node. operatorOperand
1773
1791
let rhs = node. rightOperand
1774
1792
maybeGroupAroundSubexpression ( rhs, combiningOperator: binOp)
@@ -2514,14 +2532,22 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2514
2532
/// trivia represents a malformed input (as opposed to garbage text in leading trivia, which has
2515
2533
/// some legitimate uses), this is a reasonable compromise to keep the garbage text roughly in the
2516
2534
/// same place but still let surrounding formatting occur somewhat as expected.
2517
- private func appendTrailingTrivia( _ token: TokenSyntax ) {
2535
+ private func appendTrailingTrivia( _ token: TokenSyntax , forced : Bool = false ) {
2518
2536
let trailingTrivia = Array ( token. trailingTrivia)
2519
- guard let lastUnexpectedIndex = trailingTrivia. lastIndex ( where: { $0. isUnexpectedText } ) else {
2520
- return
2537
+ let lastIndex : Array < TriviaPiece > . Index
2538
+ if forced {
2539
+ lastIndex = trailingTrivia. index ( before: trailingTrivia. endIndex)
2540
+ } else {
2541
+ guard
2542
+ let lastUnexpectedIndex = trailingTrivia. lastIndex ( where: { $0. isUnexpectedText } )
2543
+ else {
2544
+ return
2545
+ }
2546
+ lastIndex = lastUnexpectedIndex
2521
2547
}
2522
2548
2523
2549
var verbatimText = " "
2524
- for piece in trailingTrivia [ ... lastUnexpectedIndex ] {
2550
+ for piece in trailingTrivia [ ... lastIndex ] {
2525
2551
switch piece {
2526
2552
case . shebang, . unexpectedText, . spaces, . tabs, . formfeeds, . verticalTabs:
2527
2553
piece. write ( to: & verbatimText)
0 commit comments