Skip to content

Fix swift-format after https://github.com/apple/swift-syntax/pull/1010. #436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 12 additions & 22 deletions Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
before(node.result.firstToken, tokens: .break)

if let accessorOrCodeBlock = node.accessor {
arrangeAccessorOrCodeBlock(accessorOrCodeBlock)
switch accessorOrCodeBlock {
case .accessors(let accessorBlock):
arrangeBracesAndContents(of: accessorBlock)
case .getter(let codeBlock):
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
}
}

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

/// Applies formatting tokens to the given syntax node, assuming that it is either an
/// `AccessorBlockSyntax` or a `CodeBlockSyntax`.
///
/// - Parameter node: The syntax node to arrange.
private func arrangeAccessorOrCodeBlock(_ node: Syntax) {
switch node.as(SyntaxEnum.self) {
case .accessorBlock(let accessorBlock):
arrangeBracesAndContents(of: accessorBlock)
case .codeBlock(let codeBlock):
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
default:
preconditionFailure(
"""
This should be unreachable; we expected an AccessorBlockSyntax or a CodeBlockSyntax, but \
found: \(type(of: node))
"""
)
}
}

/// Applies formatting tokens to the tokens in the given function or function-like declaration
/// node (e.g., initializers, deinitiailizers, and subscripts).
private func arrangeFunctionLikeDecl<Node: BracedSyntax, BodyContents: SyntaxCollection>(
Expand Down Expand Up @@ -1985,7 +1970,12 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
}

if let accessorOrCodeBlock = node.accessor {
arrangeAccessorOrCodeBlock(accessorOrCodeBlock)
switch accessorOrCodeBlock {
case .accessors(let accessorBlock):
arrangeBracesAndContents(of: accessorBlock)
case .getter(let codeBlock):
arrangeBracesAndContents(of: codeBlock, contentsKeyPath: \.statements)
}
} else if let trailingComma = node.trailingComma {
// If this is one of multiple comma-delimited bindings, move any pending close breaks to
// follow the comma so that it doesn't get separated from the tokens before it.
Expand Down
118 changes: 60 additions & 58 deletions Sources/SwiftFormatRules/FileScopedDeclarationPrivacy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,68 +38,70 @@ public final class FileScopedDeclarationPrivacy: SyntaxFormatRule {
-> CodeBlockItemListSyntax
{
let newCodeBlockItems = codeBlockItems.map { codeBlockItem -> CodeBlockItemSyntax in
switch codeBlockItem.item.as(SyntaxEnum.self) {
case .ifConfigDecl(let ifConfigDecl):
// We need to look through `#if/#elseif/#else` blocks because the decls directly inside
// them are still considered file-scope for our purposes.
return codeBlockItem.withItem(Syntax(rewrittenIfConfigDecl(ifConfigDecl)))

case .functionDecl(let functionDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
functionDecl,
modifiers: functionDecl.modifiers,
factory: functionDecl.withModifiers)))

case .variableDecl(let variableDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
variableDecl,
modifiers: variableDecl.modifiers,
factory: variableDecl.withModifiers)))

case .classDecl(let classDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
classDecl,
modifiers: classDecl.modifiers,
factory: classDecl.withModifiers)))

case .structDecl(let structDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
structDecl,
modifiers: structDecl.modifiers,
factory: structDecl.withModifiers)))

case .enumDecl(let enumDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
enumDecl,
modifiers: enumDecl.modifiers,
factory: enumDecl.withModifiers)))

case .protocolDecl(let protocolDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
protocolDecl,
modifiers: protocolDecl.modifiers,
factory: protocolDecl.withModifiers)))

case .typealiasDecl(let typealiasDecl):
return codeBlockItem.withItem(
Syntax(rewrittenDecl(
typealiasDecl,
modifiers: typealiasDecl.modifiers,
factory: typealiasDecl.withModifiers)))

switch codeBlockItem.item {
case .decl(let decl):
return codeBlockItem.withItem(.decl(rewrittenDecl(decl)))
default:
return codeBlockItem
}
}
return CodeBlockItemListSyntax(newCodeBlockItems)
}

private func rewrittenDecl(_ decl: DeclSyntax) -> DeclSyntax {
switch Syntax(decl).as(SyntaxEnum.self) {
case .ifConfigDecl(let ifConfigDecl):
// We need to look through `#if/#elseif/#else` blocks because the decls directly inside
// them are still considered file-scope for our purposes.
return DeclSyntax(rewrittenIfConfigDecl(ifConfigDecl))

case .functionDecl(let functionDecl):
return DeclSyntax(rewrittenDecl(
functionDecl,
modifiers: functionDecl.modifiers,
factory: functionDecl.withModifiers))

case .variableDecl(let variableDecl):
return DeclSyntax(rewrittenDecl(
variableDecl,
modifiers: variableDecl.modifiers,
factory: variableDecl.withModifiers))

case .classDecl(let classDecl):
return DeclSyntax(rewrittenDecl(
classDecl,
modifiers: classDecl.modifiers,
factory: classDecl.withModifiers))

case .structDecl(let structDecl):
return DeclSyntax(rewrittenDecl(
structDecl,
modifiers: structDecl.modifiers,
factory: structDecl.withModifiers))

case .enumDecl(let enumDecl):
return DeclSyntax(rewrittenDecl(
enumDecl,
modifiers: enumDecl.modifiers,
factory: enumDecl.withModifiers))

case .protocolDecl(let protocolDecl):
return DeclSyntax(rewrittenDecl(
protocolDecl,
modifiers: protocolDecl.modifiers,
factory: protocolDecl.withModifiers))

case .typealiasDecl(let typealiasDecl):
return DeclSyntax(rewrittenDecl(
typealiasDecl,
modifiers: typealiasDecl.modifiers,
factory: typealiasDecl.withModifiers))

default:
return decl
}
}

/// Returns a new `IfConfigDeclSyntax` equivalent to the given node, but where any file-scoped
/// declarations with effective private access have had their formal access level rewritten, if
/// necessary, to be either `private` or `fileprivate`, as determined by the formatter
Expand All @@ -109,9 +111,9 @@ public final class FileScopedDeclarationPrivacy: SyntaxFormatRule {
/// - Returns: A new `IfConfigDeclSyntax` that has possibly been rewritten.
private func rewrittenIfConfigDecl(_ ifConfigDecl: IfConfigDeclSyntax) -> IfConfigDeclSyntax {
let newClauses = ifConfigDecl.clauses.map { clause -> IfConfigClauseSyntax in
switch clause.elements?.as(SyntaxEnum.self) {
case .codeBlockItemList(let codeBlockItemList)?:
return clause.withElements(Syntax(rewrittenCodeBlockItems(codeBlockItemList)))
switch clause.elements {
case .statements(let codeBlockItemList)?:
return clause.withElements(.statements(rewrittenCodeBlockItems(codeBlockItemList)))
default:
return clause
}
Expand Down
26 changes: 18 additions & 8 deletions Sources/SwiftFormatRules/NoCasesWithOnlyFallthrough.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import SwiftSyntax
public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {

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

/// Flushes any un-collapsed violations to the new cases list.
func flushViolations() {
fallthroughOnlyCases.forEach {
newChildren.append(Syntax(super.visit($0)))
newChildren.append(.switchCase(super.visit($0)))
}
fallthroughOnlyCases.removeAll()
}
Expand All @@ -50,14 +50,14 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
guard !fallthroughOnlyCases.isEmpty else {
// If there are no violations recorded, just append the case. There's nothing we can try
// to merge into it.
newChildren.append(Syntax(visit(switchCase)))
newChildren.append(.switchCase(visit(switchCase)))
continue
}

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

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

/// Returns true if this node or one of its descendents is a `ValueBindingPatternSyntax`.
private func containsValueBindingPattern(_ node: SwitchCaseSyntax.Label) -> Bool {
switch node {
case .case(let label):
return containsValueBindingPattern(Syntax(label))
case .default:
return false
}
}

/// Returns true if this node or one of its descendents is a `ValueBindingPatternSyntax`.
private func containsValueBindingPattern(_ node: Syntax) -> Bool {
if node.is(ValueBindingPatternSyntax.self) {
Expand Down Expand Up @@ -178,8 +188,8 @@ public final class NoCasesWithOnlyFallthrough: SyntaxFormatRule {
}
newCaseItems.append(contentsOf: labels.last!.caseItems)

let newCase = cases.last!.withLabel(
Syntax(labels.last!.withCaseItems(CaseItemListSyntax(newCaseItems))))
let newCase = cases.last!.withLabel(.case(
labels.last!.withCaseItems(CaseItemListSyntax(newCaseItems))))

// Only the first violation case can have displaced trivia, because any non-whitespace
// trivia in the other violation cases would've prevented collapsing.
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormatRules/NoParensAroundConditions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public final class NoParensAroundConditions: SyntaxFormatRule {
else {
return super.visit(node)
}
return node.withCondition(Syntax(extractExpr(tup)))
return node.withCondition(.expression(extractExpr(tup)))
}

/// FIXME(hbh): Parsing for SwitchStmtSyntax is not implemented.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public final class OneVariableDeclarationPerLine: SyntaxFormatRule {
let visitedDecl = super.visit(varDecl).as(VariableDeclSyntax.self)!
var splitter = VariableDeclSplitter {
CodeBlockItemSyntax(
item: Syntax($0),
item: .decl(DeclSyntax($0)),
semicolon: nil,
errorTokens: nil)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ public final class ReturnVoidInsteadOfEmptyTuple: SyntaxFormatRule {
return super.visit(node)
}

let input: Syntax?
if let parameterClause = node.input?.as(ParameterClauseSyntax.self) {
let input: ClosureSignatureSyntax.Input?
switch node.input {
case .input(let parameterClause)?:
// If the closure input is a complete parameter clause (variables and types), make sure that
// nested function types are also rewritten (for example, `label: (Int -> ()) -> ()` should
// become `label: (Int -> Void) -> Void`).
input = Syntax(visit(parameterClause))
} else {
input = .input(visit(parameterClause))
default:
// Otherwise, it's a simple signature (just variable names, no types), so there is nothing to
// rewrite.
input = node.input
Expand Down
19 changes: 13 additions & 6 deletions Sources/SwiftFormatRules/UseEarlyExits.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ public final class UseEarlyExits: SyntaxFormatRule {
elseKeyword: TokenSyntax.elseKeyword(trailingTrivia: .spaces(1)),
body: elseBody)

return [
CodeBlockItemSyntax(item: Syntax(guardStatement), semicolon: nil, errorTokens: nil),
CodeBlockItemSyntax(item: Syntax(trueBlock), semicolon: nil, errorTokens: nil),
var items = [
CodeBlockItemSyntax(
item: .stmt(StmtSyntax(guardStatement)), semicolon: nil, errorTokens: nil),
]
items.append(contentsOf: trueBlock.statements)
return items
})
return result
}
Expand All @@ -89,9 +91,14 @@ public final class UseEarlyExits: SyntaxFormatRule {
private func codeBlockEndsWithEarlyExit(_ codeBlock: CodeBlockSyntax) -> Bool {
guard let lastStatement = codeBlock.statements.last else { return false }

switch lastStatement.item.as(SyntaxEnum.self) {
case .returnStmt, .throwStmt, .breakStmt, .continueStmt:
return true
switch lastStatement.item {
case .stmt(let stmt):
switch Syntax(stmt).as(SyntaxEnum.self) {
case .returnStmt, .throwStmt, .breakStmt, .continueStmt:
return true
default:
return false
}
default:
return false
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormatRules/UseShorthandTypeNames.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public final class UseShorthandTypeNames: SyntaxFormatRule {
])
return DictionaryExprSyntax(
leftSquare: leftSquareBracket,
content: Syntax(dictElementList),
content: .elements(dictElementList),
rightSquare: rightSquareBracket)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public final class UseSingleLinePropertyGetter: SyntaxFormatRule {
let newBlock = CodeBlockSyntax(
leftBrace: accessorBlock.leftBrace, statements: body.statements,
rightBrace: accessorBlock.rightBrace)
return node.withAccessor(Syntax(newBlock))
return node.withAccessor(.getter(newBlock))
}
}

Expand Down
Loading