Skip to content

Commit 4e7d61e

Browse files
authored
Merge pull request #2428 from ahoppen/ahoppen/indentation-newline-at-end-of-scope
Fix indentation issue if trailing trivia contains a newline at the end of an indentation scope
2 parents 35e0bc1 + 498d311 commit 4e7d61e

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

Sources/SwiftBasicFormat/BasicFormat.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,19 @@ open class BasicFormat: SyntaxRewriter {
594594
trailingTriviaIndentation = anchorPointIndentation
595595
}
596596

597-
leadingTrivia = leadingTrivia.indented(indentation: leadingTriviaIndentation, isOnNewline: previousTokenIsStringLiteralEndingInNewline)
598-
trailingTrivia = trailingTrivia.indented(indentation: trailingTriviaIndentation, isOnNewline: false)
597+
leadingTrivia = leadingTrivia.indented(
598+
indentation: leadingTriviaIndentation,
599+
isOnNewline: previousTokenIsStringLiteralEndingInNewline || previousTokenWillEndWithNewline
600+
)
601+
trailingTrivia = trailingTrivia.indented(
602+
indentation: trailingTriviaIndentation,
603+
isOnNewline: false,
604+
// Don't add indentation to the last newline.
605+
// Its indentation will be added to the next token's leading trivia, which
606+
// might have a different indentation scope than this token (in particular
607+
// if this token is a closing brace).
608+
addIndentationAfterLastNewline: false
609+
)
599610

600611
leadingTrivia = leadingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: leadingTriviaIsFollowedByNewline)
601612
trailingTrivia = trailingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: nextTokenWillStartWithNewline)

Sources/SwiftBasicFormat/Trivia+FormatExtensions.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,20 @@ extension Trivia {
6262
}
6363

6464
/// Adds `indentation` after every newline in this trivia.
65-
func indented(indentation: Trivia, isOnNewline: Bool) -> Trivia {
65+
///
66+
/// - Parameters:
67+
/// - indentation: The amount of indentation to add.
68+
/// - isOnNewline: Whether this token starts on a new line.
69+
/// This causes the indentation to get added at the start of the trivia.
70+
/// - addIndentationAfterLastNewline: Whether to add indentation after newline
71+
/// if the newline is the last piece of trivia. Not doing this makes sense
72+
/// if the indentation will get added to the next token's leading trivia
73+
/// via `isOnNewline`.
74+
func indented(
75+
indentation: Trivia,
76+
isOnNewline: Bool,
77+
addIndentationAfterLastNewline: Bool = true
78+
) -> Trivia {
6679
guard !isEmpty else {
6780
if isOnNewline {
6881
return indentation
@@ -72,13 +85,13 @@ extension Trivia {
7285

7386
var indentedPieces: [TriviaPiece] = []
7487
if isOnNewline {
75-
indentedPieces.append(contentsOf: indentation)
88+
indentedPieces += indentation
7689
}
7790

78-
for piece in pieces {
91+
for (index, piece) in pieces.enumerated() {
7992
indentedPieces.append(piece)
80-
if piece.isNewline {
81-
indentedPieces.append(contentsOf: indentation)
93+
if piece.isNewline && !(index == pieces.count - 1 && !addIndentationAfterLastNewline) {
94+
indentedPieces += indentation
8295
}
8396
}
8497

Tests/SwiftBasicFormatTest/BasicFormatTests.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,4 +566,47 @@ final class BasicFormatTest: XCTestCase {
566566
"""
567567
assertFormatted(source: source, expected: source)
568568
}
569+
570+
func testNewlineInTrailingTriviaAtEndOfIndentationScope() throws {
571+
assertFormatted(
572+
tree: try FunctionDeclSyntax("func test()") {
573+
CodeBlockItemSyntax("Task {\n}\n")
574+
},
575+
expected: """
576+
func test() {
577+
Task {
578+
}
579+
}
580+
"""
581+
)
582+
583+
assertFormatted(
584+
tree: try FunctionDeclSyntax("func test()") {
585+
CodeBlockItemSyntax("Task {\n}\n\n")
586+
},
587+
expected: """
588+
func test() {
589+
Task {
590+
}
591+
}
592+
"""
593+
)
594+
595+
assertFormatted(
596+
tree: try FunctionDeclSyntax("func bar()") {
597+
try FunctionDeclSyntax("func test()") {
598+
CodeBlockItemSyntax("Task {\n}\n")
599+
}
600+
},
601+
expected: """
602+
func bar() {
603+
func test() {
604+
Task {
605+
}
606+
}
607+
}
608+
"""
609+
)
610+
}
611+
569612
}

0 commit comments

Comments
 (0)