Skip to content

Commit 5d2875d

Browse files
authored
Merge pull request #2048 from ahoppen/ahoppen/incrorrect-trivia-wrapping
Fix trivia transfer bugs for freestanding expression macros
2 parents 10569a6 + 5824002 commit 5d2875d

File tree

3 files changed

+44
-49
lines changed

3 files changed

+44
-49
lines changed

Sources/SwiftSyntaxMacroExpansion/IndentationUtils.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ extension Trivia {
8585
}
8686
return Trivia(pieces: resultPieces)
8787
}
88+
89+
/// Remove all indentation from the last line of this trivia
90+
var removingIndentationOnLastLine: Trivia {
91+
let lastNewlineIndex = pieces.lastIndex(where: \.isNewline) ?? pieces.startIndex
92+
93+
return Trivia(pieces: pieces[..<lastNewlineIndex]) + Trivia(pieces: pieces[lastNewlineIndex...]).removingIndentation
94+
}
8895
}
8996

9097
extension SyntaxProtocol {

Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift

Lines changed: 13 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private func expandFreestandingMemberDeclList(
6666
let indentedSource =
6767
expanded
6868
.indented(by: node.indentationOfFirstLine)
69-
.wrappingInNonCommentTrivia(from: node)
69+
.wrappingInTrivia(from: node)
7070
return "\(raw: indentedSource)"
7171
}
7272

@@ -94,7 +94,7 @@ private func expandFreestandingCodeItemList(
9494
let indentedSource =
9595
expanded
9696
.indented(by: node.indentationOfFirstLine)
97-
.wrappingInNonCommentTrivia(from: node)
97+
.wrappingInTrivia(from: node)
9898
return "\(raw: indentedSource)"
9999
}
100100

@@ -119,7 +119,7 @@ private func expandFreestandingExpr(
119119
let indentedSource =
120120
expanded
121121
.indented(by: node.indentationOfFirstLine)
122-
.wrappingInNonCommentTrivia(from: node)
122+
.wrappingInTrivia(from: node)
123123
return "\(raw: indentedSource)"
124124
}
125125

@@ -947,17 +947,18 @@ private extension AccessorBlockSyntax {
947947
}
948948

949949
private extension String {
950-
/// Add any non-comment trivia from `node` before/after this string.
950+
/// Add any trivia from `node` before/after this string.
951951
///
952-
/// We need to do this because the macro is responsible for copying trivia
953-
/// from the freestanding macro to the generated declaration.
954-
///
955-
/// Essentially, what we want to keep any empty newlines in front of the
956-
/// freestanding macro that separate it from the previous declarations.
957-
func wrappingInNonCommentTrivia(from node: some SyntaxProtocol) -> String {
958-
return node.leadingTrivia.removingComments.removingIndentation.description
952+
/// We need to do this because we are replacing the entire macro expansion
953+
/// declaration / expression with the expanded source but semantically, the
954+
/// user should think about it as just replacing the `#...` expression without
955+
/// any trivia.
956+
func wrappingInTrivia(from node: some SyntaxProtocol) -> String {
957+
// We need to remove the indentation from the last line because the macro
958+
// expansion buffer already contains the indentation.
959+
return node.leadingTrivia.removingIndentationOnLastLine.description
959960
+ self
960-
+ node.leadingTrivia.removingComments.removingIndentation.description
961+
+ node.trailingTrivia.description
961962
}
962963
}
963964

@@ -972,37 +973,3 @@ private extension SyntaxProtocol {
972973
return self.detached
973974
}
974975
}
975-
976-
private extension Trivia {
977-
/// Drop all comments from the trivia.
978-
///
979-
/// If a comment is the only entry on a line, drop the entire line instead of
980-
/// leaving an empty line.
981-
var removingComments: Trivia {
982-
var result: [TriviaPiece] = []
983-
984-
var lineContainedComment = false
985-
var lineContainedNonWhitespaceNonComment = false
986-
for piece in self.pieces {
987-
switch piece {
988-
case .spaces, .tabs:
989-
result.append(piece)
990-
case .backslashes, .formfeeds, .pounds, .unexpectedText, .verticalTabs:
991-
lineContainedNonWhitespaceNonComment = true
992-
result.append(piece)
993-
case .blockComment, .docBlockComment, .docLineComment, .lineComment:
994-
lineContainedComment = true
995-
case .carriageReturns, .carriageReturnLineFeeds, .newlines:
996-
if lineContainedComment && !lineContainedNonWhitespaceNonComment {
997-
continue
998-
} else {
999-
result.append(piece)
1000-
}
1001-
lineContainedComment = false
1002-
lineContainedNonWhitespaceNonComment = false
1003-
}
1004-
}
1005-
1006-
return Trivia(pieces: result)
1007-
}
1008-
}

Tests/SwiftSyntaxMacroExpansionTest/MacroSystemTests.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,25 @@ final class MacroSystemTests: XCTestCase {
701701
)
702702
}
703703

704+
func testTriviaTransferOnExpressionMacro() {
705+
assertMacroExpansion(
706+
"""
707+
// Ignore me
708+
\t
709+
// Capture me
710+
#stringify(x)
711+
""",
712+
expandedSource: """
713+
// Ignore me
714+
\t
715+
// Capture me
716+
(x, "x")
717+
""",
718+
macros: testMacros,
719+
indentationWidth: indentationWidth
720+
)
721+
}
722+
704723
func testCommentsOnExpressionMacro() {
705724
assertMacroExpansion(
706725
"""
@@ -709,7 +728,7 @@ final class MacroSystemTests: XCTestCase {
709728
""",
710729
expandedSource: """
711730
let b =
712-
(x + y, "x + y")
731+
/*leading */ (x + y, "x + y") /*trailing*/
713732
""",
714733
macros: testMacros,
715734
indentationWidth: indentationWidth
@@ -1441,10 +1460,11 @@ final class MacroSystemTests: XCTestCase {
14411460
) /* trailing comment */
14421461
""",
14431462
expandedSource: """
1463+
// some comment
14441464
func foo() {
14451465
}
14461466
func bar() {
1447-
}
1467+
} /* trailing comment */
14481468
""",
14491469
macros: ["decls": DeclsFromStringsMacro.self],
14501470
indentationWidth: indentationWidth
@@ -1464,10 +1484,11 @@ final class MacroSystemTests: XCTestCase {
14641484
""",
14651485
expandedSource: """
14661486
struct Foo {
1487+
// some comment
14671488
func foo() {
14681489
}
14691490
func bar() {
1470-
}
1491+
} /* trailing comment */
14711492
}
14721493
""",
14731494
macros: ["decls": DeclsFromStringsMacro.self],

0 commit comments

Comments
 (0)