diff --git a/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift b/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift index 237dec791a3..77ad7165601 100644 --- a/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift +++ b/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift @@ -42,9 +42,15 @@ extension CodeBlockItemListBuilder { } public static func buildFinalResult(_ component: Component) -> CodeBlockItemListSyntax { - .init( - component.enumerated().map { (index, expression) in - if index > component.startIndex, !expression.leadingTrivia.contains(where: \.isNewline) { + // Treat the first element as being on a new line. It doesn't need a leading newline + var previousEndedInNewline = true + + return CodeBlockItemListSyntax( + component.map { expression in + defer { + previousEndedInNewline = expression.trailingTrivia.pieces.last?.isNewline ?? false + } + if !previousEndedInNewline, !expression.leadingTrivia.contains(where: \.isNewline) { return expression.with(\.leadingTrivia, .newline.merging(expression.leadingTrivia)) } else { return expression diff --git a/Sources/_SwiftSyntaxGenericTestSupport/AssertEqualWithDiff.swift b/Sources/_SwiftSyntaxGenericTestSupport/AssertEqualWithDiff.swift index d23a3031538..be336fe0d83 100644 --- a/Sources/_SwiftSyntaxGenericTestSupport/AssertEqualWithDiff.swift +++ b/Sources/_SwiftSyntaxGenericTestSupport/AssertEqualWithDiff.swift @@ -83,8 +83,8 @@ public func failStringsEqualWithDiff( // Use `CollectionDifference` on supported platforms to get `diff`-like line-based output. On // older platforms, fall back to simple string comparison. - let actualLines = actual.split(separator: "\n") - let expectedLines = expected.split(separator: "\n") + let actualLines = actual.split(separator: "\n", omittingEmptySubsequences: false) + let expectedLines = expected.split(separator: "\n", omittingEmptySubsequences: false) let difference = actualLines.difference(from: expectedLines) diff --git a/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift b/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift index a1e9c9a5cda..e46709a91fb 100644 --- a/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift +++ b/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift @@ -15,7 +15,7 @@ import SwiftSyntaxBuilder import XCTest final class CollectionNodeFlatteningTests: XCTestCase { - func test_FlattenCodeBlockItemListWithBuilder() { + func testFlattenCodeBlockItemListWithBuilder() { @CodeBlockItemListBuilder func buildInnerCodeBlockItemList() -> CodeBlockItemListSyntax { [ExprSyntax("innerBuilder1"), ExprSyntax("innerBuilder2")].lazy.map { @@ -47,7 +47,7 @@ final class CollectionNodeFlatteningTests: XCTestCase { ) } - func test_FlattenCodeBlockItemListWithCodeBlockItemStrings() { + func testFlattenCodeBlockItemListWithCodeBlockItemStrings() { let buildable = CodeBlockItemListSyntax { "let one = object.methodOne()" "let two = object.methodTwo()" @@ -62,7 +62,7 @@ final class CollectionNodeFlatteningTests: XCTestCase { ) } - func test_FlattenCodeBlockItemListWithCodeBlockItemStringArray() { + func testFlattenCodeBlockItemListWithCodeBlockItemStringArray() { let buildable = CodeBlockItemListSyntax { ["let one = object.methodOne()", "let two = object.methodTwo()"] } @@ -76,7 +76,7 @@ final class CollectionNodeFlatteningTests: XCTestCase { ) } - func test_FlattenCodeBlockItemListWithCodeBlockInterpolated() { + func testFlattenCodeBlockItemListWithCodeBlockInterpolated() { let block = CodeBlockItemListSyntax { "let a = 1" "let b = 2" @@ -102,4 +102,21 @@ final class CollectionNodeFlatteningTests: XCTestCase { """ ) } + + func testFlattenCodeBlockItemListWithTrailingNewline() { + let buildable = CodeBlockItemListSyntax { + DeclSyntax("let a = 1").with(\.trailingTrivia, .newline) + DeclSyntax("let b = 2").with(\.trailingTrivia, .newline) + } + + assertBuildResult( + buildable, + """ + let a = 1 + let b = 2 + + """ + ) + } + }