@@ -1799,8 +1799,23 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
1799
1799
1800
1800
override func visit( _ node: AvailabilityLabeledArgumentSyntax ) -> SyntaxVisitorContinueKind {
1801
1801
before ( node. label, tokens: . open)
1802
- after ( node. colon, tokens: . break( . continue, newlines: . elective( ignoresDiscretionary: true ) ) )
1803
- after ( node. value. lastToken ( viewMode: . sourceAccurate) , tokens: . close)
1802
+
1803
+ let tokensAfterColon : [ Token ]
1804
+ let endTokens : [ Token ]
1805
+
1806
+ if case . string( let string) = node. value,
1807
+ string. openingQuote. tokenKind == . multilineStringQuote
1808
+ {
1809
+ tokensAfterColon =
1810
+ [ . break( . open( kind: . block) , newlines: . elective( ignoresDiscretionary: true ) ) ]
1811
+ endTokens = [ . break( . close( mustBreak: false ) , size: 0 ) , . close]
1812
+ } else {
1813
+ tokensAfterColon = [ . break( . continue, newlines: . elective( ignoresDiscretionary: true ) ) ]
1814
+ endTokens = [ . close]
1815
+ }
1816
+
1817
+ after ( node. colon, tokens: tokensAfterColon)
1818
+ after ( node. value. lastToken ( viewMode: . sourceAccurate) , tokens: endTokens)
1804
1819
return . visitChildren
1805
1820
}
1806
1821
@@ -2293,6 +2308,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2293
2308
2294
2309
override func visit( _ node: GenericParameterSyntax ) -> SyntaxVisitorContinueKind {
2295
2310
before ( node. firstToken ( viewMode: . sourceAccurate) , tokens: . open)
2311
+ after ( node. eachKeyword, tokens: . break)
2296
2312
after ( node. colon, tokens: . break)
2297
2313
if let trailingComma = node. trailingComma {
2298
2314
after ( trailingComma, tokens: . close, . break( . same) )
@@ -2312,6 +2328,28 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2312
2328
return . visitChildren
2313
2329
}
2314
2330
2331
+ override func visit( _ node: PackElementExprSyntax ) -> SyntaxVisitorContinueKind {
2332
+ // `each` cannot be separated from the following token, or it is parsed as an identifier itself.
2333
+ after ( node. eachKeyword, tokens: . space)
2334
+ return . visitChildren
2335
+ }
2336
+
2337
+ override func visit( _ node: PackElementTypeSyntax ) -> SyntaxVisitorContinueKind {
2338
+ // `each` cannot be separated from the following token, or it is parsed as an identifier itself.
2339
+ after ( node. eachKeyword, tokens: . space)
2340
+ return . visitChildren
2341
+ }
2342
+
2343
+ override func visit( _ node: PackExpansionExprSyntax ) -> SyntaxVisitorContinueKind {
2344
+ after ( node. repeatKeyword, tokens: . break)
2345
+ return . visitChildren
2346
+ }
2347
+
2348
+ override func visit( _ node: PackExpansionTypeSyntax ) -> SyntaxVisitorContinueKind {
2349
+ after ( node. repeatKeyword, tokens: . break)
2350
+ return . visitChildren
2351
+ }
2352
+
2315
2353
override func visit( _ node: ExpressionPatternSyntax ) -> SyntaxVisitorContinueKind {
2316
2354
return . visitChildren
2317
2355
}
@@ -2353,6 +2391,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2353
2391
return . visitChildren
2354
2392
}
2355
2393
2394
+ override func visit( _ node: SimpleStringLiteralExprSyntax ) -> SyntaxVisitorContinueKind {
2395
+ if node. openingQuote. tokenKind == . multilineStringQuote {
2396
+ after ( node. openingQuote, tokens: . break( . same, size: 0 , newlines: . hard( count: 1 ) ) )
2397
+ if !node. segments. isEmpty {
2398
+ before ( node. closingQuote, tokens: . break( . same, newlines: . hard( count: 1 ) ) )
2399
+ }
2400
+ }
2401
+ return . visitChildren
2402
+ }
2403
+
2356
2404
override func visit( _ node: StringSegmentSyntax ) -> SyntaxVisitorContinueKind {
2357
2405
// Looks up the correct break kind based on prior context.
2358
2406
func breakKind( ) -> BreakKind {
@@ -2481,6 +2529,27 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
2481
2529
return . visitChildren
2482
2530
}
2483
2531
2532
+ override func visit( _ node: ConsumeExprSyntax ) -> SyntaxVisitorContinueKind {
2533
+ // The `consume` keyword cannot be separated from the following token or it will be parsed as
2534
+ // an identifier.
2535
+ after ( node. consumeKeyword, tokens: . space)
2536
+ return . visitChildren
2537
+ }
2538
+
2539
+ override func visit( _ node: CopyExprSyntax ) -> SyntaxVisitorContinueKind {
2540
+ // The `copy` keyword cannot be separated from the following token or it will be parsed as an
2541
+ // identifier.
2542
+ after ( node. copyKeyword, tokens: . space)
2543
+ return . visitChildren
2544
+ }
2545
+
2546
+ override func visit( _ node: DiscardStmtSyntax ) -> SyntaxVisitorContinueKind {
2547
+ // The `discard` keyword cannot be separated from the following token or it will be parsed as
2548
+ // an identifier.
2549
+ after ( node. discardKeyword, tokens: . space)
2550
+ return . visitChildren
2551
+ }
2552
+
2484
2553
override func visit( _ node: InheritanceClauseSyntax ) -> SyntaxVisitorContinueKind {
2485
2554
// Normally, the open-break is placed before the open token. In this case, it's intentionally
2486
2555
// ordered differently so that the inheritance list can start on the current line and only
0 commit comments