Skip to content

Commit 994f34b

Browse files
committed
Fix formatting of keypath subscript components with labels.
Also refine the treatment of the closing bracket so that it is only forced to go onto a new line if the subscript component is not the last component in the keypath. This aligns with how we handle closing brackets/parentheses in member access chains. Fixes #663.
1 parent 0002372 commit 994f34b

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,11 +1894,31 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
18941894
}
18951895

18961896
override func visit(_ node: KeyPathSubscriptComponentSyntax) -> SyntaxVisitorContinueKind {
1897-
after(node.leftSquare, tokens: .break(.open, size: 0), .open)
1898-
before(node.rightSquare, tokens: .break(.close, size: 0), .close)
1897+
var breakBeforeRightParen = !isCompactSingleFunctionCallArgument(node.arguments)
1898+
if let component = node.parent?.as(KeyPathComponentSyntax.self) {
1899+
breakBeforeRightParen = !isLastKeyPathComponent(component)
1900+
}
1901+
1902+
arrangeFunctionCallArgumentList(
1903+
node.arguments,
1904+
leftDelimiter: node.leftSquare,
1905+
rightDelimiter: node.rightSquare,
1906+
forcesBreakBeforeRightDelimiter: breakBeforeRightParen)
18991907
return .visitChildren
19001908
}
19011909

1910+
/// Returns a value indicating whether the given key path component was the last component in the
1911+
/// list containing it.
1912+
private func isLastKeyPathComponent(_ component: KeyPathComponentSyntax) -> Bool {
1913+
guard
1914+
let componentList = component.parent?.as(KeyPathComponentListSyntax.self),
1915+
let lastComponent = componentList.last
1916+
else {
1917+
return false
1918+
}
1919+
return component == lastComponent
1920+
}
1921+
19021922
override func visit(_ node: TernaryExprSyntax) -> SyntaxVisitorContinueKind {
19031923
// The order of the .open/.close tokens here is intentional. They are normally paired with the
19041924
// corresponding breaks, but in this case, we want to prioritize keeping the entire `? a : b`

Tests/SwiftFormatTests/PrettyPrint/KeyPathExprTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ final class KeyPathExprTests: PrettyPrintTestCase {
131131
#"""
132132
let x = \ReallyLongType.reallyLongProperty.anotherLongProperty
133133
let x = \.reeeeallyLongProperty.anotherLongProperty
134+
let x = \.longProperty.a.b.c[really + long + expression]
134135
let x = \.longProperty.a.b.c[really + long + expression].anotherLongProperty
136+
let x = \.longProperty.a.b.c[label:really + long + expression].anotherLongProperty
135137
"""#
136138

137139
let expected =
@@ -146,6 +148,16 @@ final class KeyPathExprTests: PrettyPrintTestCase {
146148
let x =
147149
\.longProperty.a.b.c[
148150
really + long
151+
+ expression]
152+
let x =
153+
\.longProperty.a.b.c[
154+
really + long
155+
+ expression
156+
].anotherLongProperty
157+
let x =
158+
\.longProperty.a.b.c[
159+
label: really
160+
+ long
149161
+ expression
150162
].anotherLongProperty
151163

0 commit comments

Comments
 (0)