Skip to content

Various trivia-related fixes. #648

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 3 commits into from
Oct 12, 2023
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
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {

override func visit(_ node: SourceFileSyntax) -> SyntaxVisitorContinueKind {
if shouldFormatterIgnore(file: node) {
appendFormatterIgnored(node: Syntax(node))
appendToken(.verbatim(Verbatim(text: "\(node)", indentingBehavior: .none)))
return .skipChildren
}
after(node.shebang, tokens: .break(.same, newlines: .soft))
Expand Down
15 changes: 10 additions & 5 deletions Sources/SwiftFormat/Rules/NoParensAroundConditions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import SwiftSyntax
public final class NoParensAroundConditions: SyntaxFormatRule {
public override func visit(_ node: IfExprSyntax) -> ExprSyntax {
var result = node
result.ifKeyword.trailingTrivia = [.spaces(1)]
fixKeywordTrailingTrivia(&result.ifKeyword.trailingTrivia)
result.conditions = visit(node.conditions)
result.body = visit(node.body)
if let elseBody = node.elseBody {
Expand All @@ -52,7 +52,7 @@ public final class NoParensAroundConditions: SyntaxFormatRule {

public override func visit(_ node: GuardStmtSyntax) -> StmtSyntax {
var result = node
result.guardKeyword.trailingTrivia = [.spaces(1)]
fixKeywordTrailingTrivia(&result.guardKeyword.trailingTrivia)
result.conditions = visit(node.conditions)
result.body = visit(node.body)
return StmtSyntax(result)
Expand All @@ -64,7 +64,7 @@ public final class NoParensAroundConditions: SyntaxFormatRule {
}

var result = node
result.switchKeyword.trailingTrivia = [.spaces(1)]
fixKeywordTrailingTrivia(&result.switchKeyword.trailingTrivia)
result.subject = newSubject
result.cases = visit(node.cases)
return ExprSyntax(result)
Expand All @@ -76,20 +76,25 @@ public final class NoParensAroundConditions: SyntaxFormatRule {
}

var result = node
result.whileKeyword.trailingTrivia = [.spaces(1)]
fixKeywordTrailingTrivia(&result.whileKeyword.trailingTrivia)
result.condition = newCondition
result.body = visit(node.body)
return StmtSyntax(result)
}

public override func visit(_ node: WhileStmtSyntax) -> StmtSyntax {
var result = node
result.whileKeyword.trailingTrivia = [.spaces(1)]
fixKeywordTrailingTrivia(&result.whileKeyword.trailingTrivia)
result.conditions = visit(node.conditions)
result.body = visit(node.body)
return StmtSyntax(result)
}

private func fixKeywordTrailingTrivia(_ trivia: inout Trivia) {
guard trivia.isEmpty else { return }
trivia = [.spaces(1)]
}

private func minimalSingleExpression(_ original: ExprSyntax) -> ExprSyntax? {
guard
let tuple = original.as(TupleExprSyntax.self),
Expand Down
20 changes: 9 additions & 11 deletions Sources/SwiftFormat/Rules/OrderedImports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -342,20 +342,18 @@ fileprivate func generateLines(codeBlockItemList: CodeBlockItemListSyntax, conte
/// replacing the trivia appropriately to ensure comments appear in the right location.
fileprivate func convertToCodeBlockItems(lines: [Line]) -> [CodeBlockItemSyntax] {
var output: [CodeBlockItemSyntax] = []
var triviaBuffer: [TriviaPiece] = []
var pendingLeadingTrivia: [TriviaPiece] = []

for line in lines {
triviaBuffer += line.leadingTrivia
pendingLeadingTrivia += line.leadingTrivia

func append(codeBlockItem: CodeBlockItemSyntax) {
// Comments and newlines are always located in the leading trivia of an AST node, so we need
// not deal with trailing trivia.
var codeBlockItem = codeBlockItem
codeBlockItem.leadingTrivia = Trivia(pieces: triviaBuffer)
codeBlockItem.leadingTrivia = Trivia(pieces: pendingLeadingTrivia)
codeBlockItem.trailingTrivia = Trivia(pieces: line.trailingTrivia)
output.append(codeBlockItem)

triviaBuffer = []
triviaBuffer += line.trailingTrivia
pendingLeadingTrivia = []
}

if let syntaxNode = line.syntaxNode {
Expand All @@ -367,11 +365,11 @@ fileprivate func convertToCodeBlockItems(lines: [Line]) -> [CodeBlockItemSyntax]
}
}

// Merge multiple newlines together into a single trivia piece by updating it's N value.
if let lastPiece = triviaBuffer.last, case .newlines(let N) = lastPiece {
triviaBuffer[triviaBuffer.endIndex - 1] = TriviaPiece.newlines(N + 1)
// Merge multiple newlines together into a single trivia piece by updating its count.
if let lastPiece = pendingLeadingTrivia.last, case .newlines(let count) = lastPiece {
pendingLeadingTrivia[pendingLeadingTrivia.endIndex - 1] = .newlines(count + 1)
} else {
triviaBuffer.append(TriviaPiece.newlines(1))
pendingLeadingTrivia.append(.newlines(1))
}
}

Expand Down
34 changes: 8 additions & 26 deletions Tests/SwiftFormatTests/PrettyPrint/IgnoreNodeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,36 +318,18 @@ final class IgnoreNodeTests: PrettyPrintTestCase {
{
var bazzle = 0 }
"""
assertPrettyPrintEqual(input: input, expected: input, linelength: 50)
}

let expected =
func testIgnoreWholeFileDoesNotTouchWhitespace() {
let input =
"""
// swift-format-ignore-file
import Zoo
import Aoo
import foo

struct Foo {
private var baz: Bool {
return foo +
bar + // poorly placed comment
false
}

var a = true // line comment
// aligned line comment
var b = false // correct trailing comment

var c = 0 +
1
+ (2 + 3)
}

class Bar
{
var bazzle = 0 }
/// foo bar
\u{0020}
// baz
"""

assertPrettyPrintEqual(input: input, expected: expected, linelength: 50)
assertPrettyPrintEqual(input: input, expected: input, linelength: 100)
}

func testIgnoreWholeFileInNestedNode() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,77 @@ final class NoParensAroundConditionsTests: LintOrFormatRuleTestCase {
FindingSpec("7️⃣", message: "remove the parentheses around this expression"),
]
)
}

func testBlockCommentsBeforeConditionArePreserved() {
assertFormatting(
NoParensAroundConditions.self,
input: """
if/*foo*/1️⃣(x) {}
while/*foo*/2️⃣(x) {}
guard/*foo*/3️⃣(x), /*foo*/4️⃣(y), /*foo*/5️⃣(x == 3) else {}
repeat {} while/*foo*/6️⃣(x)
switch/*foo*/7️⃣(4) { default: break }
""",
expected: """
if/*foo*/x {}
while/*foo*/x {}
guard/*foo*/x, /*foo*/y, /*foo*/x == 3 else {}
repeat {} while/*foo*/x
switch/*foo*/4 { default: break }
""",
findings: [
FindingSpec("1️⃣", message: "remove the parentheses around this expression"),
FindingSpec("2️⃣", message: "remove the parentheses around this expression"),
FindingSpec("3️⃣", message: "remove the parentheses around this expression"),
FindingSpec("4️⃣", message: "remove the parentheses around this expression"),
FindingSpec("5️⃣", message: "remove the parentheses around this expression"),
FindingSpec("6️⃣", message: "remove the parentheses around this expression"),
FindingSpec("7️⃣", message: "remove the parentheses around this expression"),
]
)
}

func testCommentsAfterKeywordArePreserved() {
assertFormatting(
NoParensAroundConditions.self,
input: """
if /*foo*/ // bar
1️⃣(x) {}
while /*foo*/ // bar
2️⃣(x) {}
guard /*foo*/ // bar
3️⃣(x), /*foo*/ // bar
4️⃣(y), /*foo*/ // bar
5️⃣(x == 3) else {}
repeat {} while /*foo*/ // bar
6️⃣(x)
switch /*foo*/ // bar
7️⃣(4) { default: break }
""",
expected: """
if /*foo*/ // bar
x {}
while /*foo*/ // bar
x {}
guard /*foo*/ // bar
x, /*foo*/ // bar
y, /*foo*/ // bar
x == 3 else {}
repeat {} while /*foo*/ // bar
x
switch /*foo*/ // bar
4 { default: break }
""",
findings: [
FindingSpec("1️⃣", message: "remove the parentheses around this expression"),
FindingSpec("2️⃣", message: "remove the parentheses around this expression"),
FindingSpec("3️⃣", message: "remove the parentheses around this expression"),
FindingSpec("4️⃣", message: "remove the parentheses around this expression"),
FindingSpec("5️⃣", message: "remove the parentheses around this expression"),
FindingSpec("6️⃣", message: "remove the parentheses around this expression"),
FindingSpec("7️⃣", message: "remove the parentheses around this expression"),
]
)
}
}