From bd5dc8d332eeb3fbfcec59cf713369b13dbbc76c Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Date: Wed, 11 Sep 2024 14:33:10 -0300 Subject: [PATCH 1/2] Add `buildFinalResult` to `CodeBlockItemListBuilder` to ensure newline between expressions --- .../ResultBuilderExtensions.swift | 12 +++++++++ .../CollectionNodeFlatteningTests.swift | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift b/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift index cdd7f591342..237dec791a3 100644 --- a/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift +++ b/Sources/SwiftSyntaxBuilder/ResultBuilderExtensions.swift @@ -40,6 +40,18 @@ extension CodeBlockItemListBuilder { public static func buildExpression(_ expression: some Sequence) -> Component { buildExpression(expression.map { CodeBlockItemSyntax(item: .decl(DeclSyntax($0))) }) } + + public static func buildFinalResult(_ component: Component) -> CodeBlockItemListSyntax { + .init( + component.enumerated().map { (index, expression) in + if index > component.startIndex, !expression.leadingTrivia.contains(where: \.isNewline) { + return expression.with(\.leadingTrivia, .newline.merging(expression.leadingTrivia)) + } else { + return expression + } + } + ) + } } extension ConditionElementListBuilder { diff --git a/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift b/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift index e54c06ac721..a1e9c9a5cda 100644 --- a/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift +++ b/Tests/SwiftSyntaxBuilderTest/CollectionNodeFlatteningTests.swift @@ -75,4 +75,31 @@ final class CollectionNodeFlatteningTests: XCTestCase { """ ) } + + func test_FlattenCodeBlockItemListWithCodeBlockInterpolated() { + let block = CodeBlockItemListSyntax { + "let a = 1" + "let b = 2" + "let c = 3" + } + + let buildable = CodeBlockItemListSyntax { + "let one = object.methodOne()" + "let two = object.methodTwo()" + "let three = {\(block)}()" + } + + assertBuildResult( + buildable, + """ + let one = object.methodOne() + let two = object.methodTwo() + let three = { + let a = 1 + let b = 2 + let c = 3 + }() + """ + ) + } } From 95f5aa69e87264e4881cddee0099b6670c474b89 Mon Sep 17 00:00:00 2001 From: Mateus Rodrigues Date: Wed, 11 Sep 2024 14:33:52 -0300 Subject: [PATCH 2/2] Replace `joined(separator:)` in `collapse` with custom logic to avoid adding unnecessary separators --- .../SwiftSyntaxMacroExpansion/MacroExpansion.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift index b2f9d6bfa82..b3cd0d25e0a 100644 --- a/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift +++ b/Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift @@ -528,5 +528,15 @@ public func collapse( break } - return expansions.joined(separator: separator) + // Join the expansions ensuring `separator` between them. + var collapsed = "" + for expansion in expansions { + if collapsed.isEmpty || expansion.hasPrefix(separator) { + collapsed.append(expansion) + } else { + collapsed.append(separator + expansion) + } + } + + return collapsed }