diff --git a/Sources/SwiftBasicFormat/BasicFormat.swift b/Sources/SwiftBasicFormat/BasicFormat.swift index 9a8092cd171..f1c7c4fb717 100644 --- a/Sources/SwiftBasicFormat/BasicFormat.swift +++ b/Sources/SwiftBasicFormat/BasicFormat.swift @@ -433,6 +433,19 @@ open class BasicFormat: SyntaxRewriter { return trailingTrivia + Trivia(pieces: nextTokenLeadingWhitespace) }() + /// Whether the leading trivia of the token is folloed by a newline. + let leadingTriviaIsFollowedByNewline: Bool = { + if token.text.isEmpty && token.trailingTrivia.startsWithNewline { + return true + } else if token.text.first?.isNewline ?? false { + return true + } else if token.text.isEmpty && token.trailingTrivia.isEmpty && nextTokenWillStartWithNewline { + return true + } else { + return false + } + }() + var leadingTrivia = token.leadingTrivia var trailingTrivia = token.trailingTrivia @@ -455,9 +468,11 @@ open class BasicFormat: SyntaxRewriter { } } - if leadingTrivia.indentation(isOnNewline: isInitialToken || previousTokenWillEndWithNewline) == [] { + let isEmptyLine = token.leadingTrivia.isEmpty && leadingTriviaIsFollowedByNewline + if leadingTrivia.indentation(isOnNewline: isInitialToken || previousTokenWillEndWithNewline) == [] && !isEmptyLine { // If the token starts on a new line and does not have indentation, this - // is the last non-indented token. Store its indentation level + // is the last non-indented token. Store its indentation level. + // Do not store the indentation level if the line is empty. anchorPoints[token] = currentIndentationLevel } @@ -501,7 +516,7 @@ open class BasicFormat: SyntaxRewriter { leadingTrivia = leadingTrivia.indented(indentation: leadingTriviaIndentation, isOnNewline: previousTokenIsStringLiteralEndingInNewline) trailingTrivia = trailingTrivia.indented(indentation: trailingTriviaIndentation, isOnNewline: false) - leadingTrivia = leadingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: false) + leadingTrivia = leadingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: leadingTriviaIsFollowedByNewline) trailingTrivia = trailingTrivia.trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: nextTokenWillStartWithNewline) if leadingTrivia == token.leadingTrivia && trailingTrivia == token.trailingTrivia { diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 8dd03faa837..d903af4a0e6 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -250,6 +250,27 @@ final class BasicFormatTest: XCTestCase { ) } + func testMultilineStringLiteralWithBlackLines() { + assertFormatted( + source: #""" + assertionFailure(""" + First line + + Second line + + """) + """#, + expected: #""" + assertionFailure(""" + First line + + Second line + + """) + """# + ) + } + func testNestedUserDefinedIndentation() { assertFormatted( source: """