Skip to content

Commit 9f5b8e3

Browse files
committed
Fix swift-format after swiftlang/swift-syntax#1010.
That swift-syntax change switched many accessors that degraded to `Syntax` type to return enums of their possibilities instead. DO NOT MERGE this still has one failing test.
1 parent 7923448 commit 9f5b8e3

10 files changed

+129
-107
lines changed

Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
397397
before(node.result.firstToken, tokens: .break)
398398

399399
if let accessorOrCodeBlock = node.accessor {
400-
arrangeAccessorOrCodeBlock(accessorOrCodeBlock)
400+
switch accessorOrCodeBlock {
401+
case .accessors(let accessorBlock):
402+
arrangeBracesAndContents(of: accessorBlock)
403+
case .getter(let codeBlock):
404+
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
405+
}
401406
}
402407

403408
after(node.lastToken, tokens: .close)
@@ -407,26 +412,6 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
407412
return .visitChildren
408413
}
409414

410-
/// Applies formatting tokens to the given syntax node, assuming that it is either an
411-
/// `AccessorBlockSyntax` or a `CodeBlockSyntax`.
412-
///
413-
/// - Parameter node: The syntax node to arrange.
414-
private func arrangeAccessorOrCodeBlock(_ node: Syntax) {
415-
switch node.as(SyntaxEnum.self) {
416-
case .accessorBlock(let accessorBlock):
417-
arrangeBracesAndContents(of: accessorBlock)
418-
case .codeBlock(let codeBlock):
419-
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
420-
default:
421-
preconditionFailure(
422-
"""
423-
This should be unreachable; we expected an AccessorBlockSyntax or a CodeBlockSyntax, but \
424-
found: \(type(of: node))
425-
"""
426-
)
427-
}
428-
}
429-
430415
/// Applies formatting tokens to the tokens in the given function or function-like declaration
431416
/// node (e.g., initializers, deinitiailizers, and subscripts).
432417
private func arrangeFunctionLikeDecl<Node: BracedSyntax, BodyContents: SyntaxCollection>(
@@ -1985,7 +1970,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
19851970
}
19861971

19871972
if let accessorOrCodeBlock = node.accessor {
1988-
arrangeAccessorOrCodeBlock(accessorOrCodeBlock)
1973+
switch accessorOrCodeBlock {
1974+
case .accessors(let accessorBlock):
1975+
arrangeBracesAndContents(of: accessorBlock)
1976+
case .getter(let codeBlock):
1977+
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
1978+
}
19891979
} else if let trailingComma = node.trailingComma {
19901980
// If this is one of multiple comma-delimited bindings, move any pending close breaks to
19911981
// follow the comma so that it doesn't get separated from the tokens before it.

Sources/SwiftFormatRules/FileScopedDeclarationPrivacy.swift

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -38,68 +38,70 @@ public final class FileScopedDeclarationPrivacy: SyntaxFormatRule {
3838
-> CodeBlockItemListSyntax
3939
{
4040
let newCodeBlockItems = codeBlockItems.map { codeBlockItem -> CodeBlockItemSyntax in
41-
switch codeBlockItem.item.as(SyntaxEnum.self) {
42-
case .ifConfigDecl(let ifConfigDecl):
43-
// We need to look through `#if/#elseif/#else` blocks because the decls directly inside
44-
// them are still considered file-scope for our purposes.
45-
return codeBlockItem.withItem(Syntax(rewrittenIfConfigDecl(ifConfigDecl)))
46-
47-
case .functionDecl(let functionDecl):
48-
return codeBlockItem.withItem(
49-
Syntax(rewrittenDecl(
50-
functionDecl,
51-
modifiers: functionDecl.modifiers,
52-
factory: functionDecl.withModifiers)))
53-
54-
case .variableDecl(let variableDecl):
55-
return codeBlockItem.withItem(
56-
Syntax(rewrittenDecl(
57-
variableDecl,
58-
modifiers: variableDecl.modifiers,
59-
factory: variableDecl.withModifiers)))
60-
61-
case .classDecl(let classDecl):
62-
return codeBlockItem.withItem(
63-
Syntax(rewrittenDecl(
64-
classDecl,
65-
modifiers: classDecl.modifiers,
66-
factory: classDecl.withModifiers)))
67-
68-
case .structDecl(let structDecl):
69-
return codeBlockItem.withItem(
70-
Syntax(rewrittenDecl(
71-
structDecl,
72-
modifiers: structDecl.modifiers,
73-
factory: structDecl.withModifiers)))
74-
75-
case .enumDecl(let enumDecl):
76-
return codeBlockItem.withItem(
77-
Syntax(rewrittenDecl(
78-
enumDecl,
79-
modifiers: enumDecl.modifiers,
80-
factory: enumDecl.withModifiers)))
81-
82-
case .protocolDecl(let protocolDecl):
83-
return codeBlockItem.withItem(
84-
Syntax(rewrittenDecl(
85-
protocolDecl,
86-
modifiers: protocolDecl.modifiers,
87-
factory: protocolDecl.withModifiers)))
88-
89-
case .typealiasDecl(let typealiasDecl):
90-
return codeBlockItem.withItem(
91-
Syntax(rewrittenDecl(
92-
typealiasDecl,
93-
modifiers: typealiasDecl.modifiers,
94-
factory: typealiasDecl.withModifiers)))
95-
41+
switch codeBlockItem.item {
42+
case .decl(let decl):
43+
return codeBlockItem.withItem(.decl(rewrittenDecl(decl)))
9644
default:
9745
return codeBlockItem
9846
}
9947
}
10048
return CodeBlockItemListSyntax(newCodeBlockItems)
10149
}
10250

51+
private func rewrittenDecl(_ decl: DeclSyntax) -> DeclSyntax {
52+
switch Syntax(decl).as(SyntaxEnum.self) {
53+
case .ifConfigDecl(let ifConfigDecl):
54+
// We need to look through `#if/#elseif/#else` blocks because the decls directly inside
55+
// them are still considered file-scope for our purposes.
56+
return DeclSyntax(rewrittenIfConfigDecl(ifConfigDecl))
57+
58+
case .functionDecl(let functionDecl):
59+
return DeclSyntax(rewrittenDecl(
60+
functionDecl,
61+
modifiers: functionDecl.modifiers,
62+
factory: functionDecl.withModifiers))
63+
64+
case .variableDecl(let variableDecl):
65+
return DeclSyntax(rewrittenDecl(
66+
variableDecl,
67+
modifiers: variableDecl.modifiers,
68+
factory: variableDecl.withModifiers))
69+
70+
case .classDecl(let classDecl):
71+
return DeclSyntax(rewrittenDecl(
72+
classDecl,
73+
modifiers: classDecl.modifiers,
74+
factory: classDecl.withModifiers))
75+
76+
case .structDecl(let structDecl):
77+
return DeclSyntax(rewrittenDecl(
78+
structDecl,
79+
modifiers: structDecl.modifiers,
80+
factory: structDecl.withModifiers))
81+
82+
case .enumDecl(let enumDecl):
83+
return DeclSyntax(rewrittenDecl(
84+
enumDecl,
85+
modifiers: enumDecl.modifiers,
86+
factory: enumDecl.withModifiers))
87+
88+
case .protocolDecl(let protocolDecl):
89+
return DeclSyntax(rewrittenDecl(
90+
protocolDecl,
91+
modifiers: protocolDecl.modifiers,
92+
factory: protocolDecl.withModifiers))
93+
94+
case .typealiasDecl(let typealiasDecl):
95+
return DeclSyntax(rewrittenDecl(
96+
typealiasDecl,
97+
modifiers: typealiasDecl.modifiers,
98+
factory: typealiasDecl.withModifiers))
99+
100+
default:
101+
return decl
102+
}
103+
}
104+
103105
/// Returns a new `IfConfigDeclSyntax` equivalent to the given node, but where any file-scoped
104106
/// declarations with effective private access have had their formal access level rewritten, if
105107
/// necessary, to be either `private` or `fileprivate`, as determined by the formatter
@@ -109,9 +111,9 @@ public final class FileScopedDeclarationPrivacy: SyntaxFormatRule {
109111
/// - Returns: A new `IfConfigDeclSyntax` that has possibly been rewritten.
110112
private func rewrittenIfConfigDecl(_ ifConfigDecl: IfConfigDeclSyntax) -> IfConfigDeclSyntax {
111113
let newClauses = ifConfigDecl.clauses.map { clause -> IfConfigClauseSyntax in
112-
switch clause.elements?.as(SyntaxEnum.self) {
113-
case .codeBlockItemList(let codeBlockItemList)?:
114-
return clause.withElements(Syntax(rewrittenCodeBlockItems(codeBlockItemList)))
114+
switch clause.elements {
115+
case .statements(let codeBlockItemList)?:
116+
return clause.withElements(.statements(rewrittenCodeBlockItems(codeBlockItemList)))
115117
default:
116118
return clause
117119
}

Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ import SwiftSyntax
2222
public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
2323

2424
public override func visit(_ node: SwitchCaseListSyntax) -> SwitchCaseListSyntax {
25-
var newChildren: [Syntax] = []
25+
var newChildren: [SwitchCaseListSyntax.Element] = []
2626
var fallthroughOnlyCases: [SwitchCaseSyntax] = []
2727

2828
/// Flushes any un-collapsed violations to the new cases list.
2929
func flushViolations() {
3030
fallthroughOnlyCases.forEach {
31-
newChildren.append(Syntax(super.visit($0)))
31+
newChildren.append(.switchCase(super.visit($0)))
3232
}
3333
fallthroughOnlyCases.removeAll()
3434
}
@@ -50,14 +50,14 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
5050
guard !fallthroughOnlyCases.isEmpty else {
5151
// If there are no violations recorded, just append the case. There's nothing we can try
5252
// to merge into it.
53-
newChildren.append(Syntax(visit(switchCase)))
53+
newChildren.append(.switchCase(visit(switchCase)))
5454
continue
5555
}
5656

5757
if canMergeWithPreviousCases(switchCase) {
5858
// If the current case can be merged with the ones before it, merge them all, leaving no
5959
// `fallthrough`-only cases behind.
60-
newChildren.append(Syntax(visit(mergedCases(fallthroughOnlyCases + [switchCase]))))
60+
newChildren.append(.switchCase(visit(mergedCases(fallthroughOnlyCases + [switchCase]))))
6161
} else {
6262
// If the current case can't be merged with the ones before it, merge the previous ones
6363
// into a single `fallthrough`-only case and then append the current one. This could
@@ -71,8 +71,8 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
7171
// the program's behavior.
7272
// 3. The current case is `@unknown default`, which can't be merged notwithstanding the
7373
// side-effect issues discussed above.
74-
newChildren.append(Syntax(visit(mergedCases(fallthroughOnlyCases))))
75-
newChildren.append(Syntax(visit(switchCase)))
74+
newChildren.append(.switchCase(visit(mergedCases(fallthroughOnlyCases))))
75+
newChildren.append(.switchCase(visit(switchCase)))
7676
}
7777

7878
fallthroughOnlyCases.removeAll()
@@ -91,6 +91,16 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
9191
return node.label.is(SwitchCaseLabelSyntax.self) && !containsValueBindingPattern(node.label)
9292
}
9393

94+
/// Returns true if this node or one of its descendents is a `ValueBindingPatternSyntax`.
95+
private func containsValueBindingPattern(_ node: SwitchCaseSyntax.Label) -> Bool {
96+
switch node {
97+
case .case(let label):
98+
return containsValueBindingPattern(Syntax(label))
99+
case .default:
100+
return false
101+
}
102+
}
103+
94104
/// Returns true if this node or one of its descendents is a `ValueBindingPatternSyntax`.
95105
private func containsValueBindingPattern(_ node: Syntax) -> Bool {
96106
if node.is(ValueBindingPatternSyntax.self) {
@@ -178,8 +188,8 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
178188
}
179189
newCaseItems.append(contentsOf: labels.last!.caseItems)
180190

181-
let newCase = cases.last!.withLabel(
182-
Syntax(labels.last!.withCaseItems(CaseItemListSyntax(newCaseItems))))
191+
let newCase = cases.last!.withLabel(.case(
192+
labels.last!.withCaseItems(CaseItemListSyntax(newCaseItems))))
183193

184194
// Only the first violation case can have displaced trivia, because any non-whitespace
185195
// trivia in the other violation cases would've prevented collapsing.

Sources/SwiftFormatRules/NoParensAroundConditions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public final class NoParensAroundConditions: SyntaxFormatRule {
6969
else {
7070
return super.visit(node)
7171
}
72-
return node.withCondition(Syntax(extractExpr(tup)))
72+
return node.withCondition(.expression(extractExpr(tup)))
7373
}
7474

7575
/// FIXME(hbh): Parsing for SwitchStmtSyntax is not implemented.

Sources/SwiftFormatRules/OneVariableDeclarationPerLine.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public final class OneVariableDeclarationPerLine: SyntaxFormatRule {
5050
let visitedDecl = super.visit(varDecl).as(VariableDeclSyntax.self)!
5151
var splitter = VariableDeclSplitter {
5252
CodeBlockItemSyntax(
53-
item: Syntax($0),
53+
item: .decl(DeclSyntax($0)),
5454
semicolon: nil,
5555
errorTokens: nil)
5656
}

Sources/SwiftFormatRules/ReturnVoidInsteadOfEmptyTuple.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,14 @@ public final class ReturnVoidInsteadOfEmptyTuple: SyntaxFormatRule {
6464
return super.visit(node)
6565
}
6666

67-
let input: Syntax?
68-
if let parameterClause = node.input?.as(ParameterClauseSyntax.self) {
67+
let input: ClosureSignatureSyntax.Input?
68+
switch node.input {
69+
case .input(let parameterClause)?:
6970
// If the closure input is a complete parameter clause (variables and types), make sure that
7071
// nested function types are also rewritten (for example, `label: (Int -> ()) -> ()` should
7172
// become `label: (Int -> Void) -> Void`).
72-
input = Syntax(visit(parameterClause))
73-
} else {
73+
input = .input(visit(parameterClause))
74+
default:
7475
// Otherwise, it's a simple signature (just variable names, no types), so there is nothing to
7576
// rewrite.
7677
input = node.input

Sources/SwiftFormatRules/UseEarlyExits.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ public final class UseEarlyExits: SyntaxFormatRule {
7676
elseKeyword: TokenSyntax.elseKeyword(trailingTrivia: .spaces(1)),
7777
body: elseBody)
7878

79-
return [
80-
CodeBlockItemSyntax(item: Syntax(guardStatement), semicolon: nil, errorTokens: nil),
81-
CodeBlockItemSyntax(item: Syntax(trueBlock), semicolon: nil, errorTokens: nil),
79+
var items = [
80+
CodeBlockItemSyntax(
81+
item: .stmt(StmtSyntax(guardStatement)), semicolon: nil, errorTokens: nil),
8282
]
83+
items.append(contentsOf: trueBlock.statements)
84+
return items
8385
})
8486
return result
8587
}
@@ -89,9 +91,14 @@ public final class UseEarlyExits: SyntaxFormatRule {
8991
private func codeBlockEndsWithEarlyExit(_ codeBlock: CodeBlockSyntax) -> Bool {
9092
guard let lastStatement = codeBlock.statements.last else { return false }
9193

92-
switch lastStatement.item.as(SyntaxEnum.self) {
93-
case .returnStmt, .throwStmt, .breakStmt, .continueStmt:
94-
return true
94+
switch lastStatement.item {
95+
case .stmt(let stmt):
96+
switch Syntax(stmt).as(SyntaxEnum.self) {
97+
case .returnStmt, .throwStmt, .breakStmt, .continueStmt:
98+
return true
99+
default:
100+
return false
101+
}
95102
default:
96103
return false
97104
}

Sources/SwiftFormatRules/UseShorthandTypeNames.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
311311
])
312312
return DictionaryExprSyntax(
313313
leftSquare: leftSquareBracket,
314-
content: Syntax(dictElementList),
314+
content: .elements(dictElementList),
315315
rightSquare: rightSquareBracket)
316316
}
317317

Sources/SwiftFormatRules/UseSingleLinePropertyGetter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public final class UseSingleLinePropertyGetter: SyntaxFormatRule {
3838
let newBlock = CodeBlockSyntax(
3939
leftBrace: accessorBlock.leftBrace, statements: body.statements,
4040
rightBrace: accessorBlock.rightBrace)
41-
return node.withAccessor(Syntax(newBlock))
41+
return node.withAccessor(.getter(newBlock))
4242
}
4343
}
4444

0 commit comments

Comments
 (0)