Skip to content

Commit 5c6edb1

Browse files
committed
Fix Accessor Macros Attached to Properties With Trailing Comments
fixed the bug that trailing comments of a property would stay in place after macro expansion, commenting out the left brace of the newly created accessor block - the bug affected only properties without an accessor block while having trailing line comments - fixed by converting line comments/doc line comments into block comments/doc block comments - trailing comments of the initializer will be transferred to its preceding token added tests on properties with trailing comments and with/without an accessor block
1 parent 050f057 commit 5c6edb1

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,39 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
933933

934934
let expansion = expandAccessors(of: node, existingAccessors: binding.accessorBlock)
935935
if expansion.accessors != binding.accessorBlock {
936+
if binding.accessorBlock == nil {
937+
// convert line comments in the trailing trivia of a property without
938+
// an accessor block that would comment out the left brace in the newly
939+
// created accessor block
940+
941+
func convertTrivia(_ trivia: Trivia) -> [TriviaPiece] {
942+
trivia.map { piece in
943+
switch piece {
944+
case let .lineComment(lineComment):
945+
.blockComment("/*\(lineComment.dropFirst(2))*/")
946+
case let .docLineComment(docLineComment):
947+
.docBlockComment("/**\(docLineComment.dropFirst(3))*/")
948+
default:
949+
piece
950+
}
951+
}
952+
}
953+
954+
let convertedPieces =
955+
if let trailingTrivia = binding.initializer?.trailingTrivia {
956+
// compensate the leading space truncated from the accessor block below
957+
convertTrivia(trailingTrivia) + [.spaces(1)]
958+
} else {
959+
convertTrivia(binding.trailingTrivia)
960+
}
961+
962+
if binding.typeAnnotation == nil {
963+
node.bindings[node.bindings.startIndex].pattern.trailingTrivia = Trivia(pieces: convertedPieces)
964+
} else {
965+
node.bindings[node.bindings.startIndex].typeAnnotation?.trailingTrivia = Trivia(pieces: convertedPieces)
966+
}
967+
}
968+
936969
if binding.initializer != nil, expansion.expandsGetSet {
937970
// The accessor block will have a leading space, but there will already be a
938971
// space between the variable and the to-be-removed initializer. Remove the

Tests/SwiftSyntaxMacroExpansionTest/AccessorMacroTests.swift

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,95 @@ fileprivate struct ConstantOneGetter: AccessorMacro {
4444
final class AccessorMacroTests: XCTestCase {
4545
private let indentationWidth: Trivia = .spaces(2)
4646

47+
func testAccessorOnVariableDeclWithTrailingLineCommentAndNoAccessorBlock() {
48+
assertMacroExpansion(
49+
"""
50+
@constantOne
51+
var x: Int // hello
52+
""",
53+
expandedSource: """
54+
var x: Int /* hello*/ {
55+
get {
56+
return 1
57+
}
58+
}
59+
""",
60+
macros: ["constantOne": ConstantOneGetter.self],
61+
indentationWidth: indentationWidth
62+
)
63+
64+
assertMacroExpansion(
65+
"""
66+
@constantOne
67+
var x: Int /// hello
68+
""",
69+
expandedSource: """
70+
var x: Int /** hello*/ {
71+
get {
72+
return 1
73+
}
74+
}
75+
""",
76+
macros: ["constantOne": ConstantOneGetter.self],
77+
indentationWidth: indentationWidth
78+
)
79+
80+
assertMacroExpansion(
81+
"""
82+
@constantOne
83+
var x: Int = 1 /// hello
84+
""",
85+
expandedSource: """
86+
var x: Int /** hello*/ {
87+
get {
88+
return 1
89+
}
90+
}
91+
""",
92+
macros: ["constantOne": ConstantOneGetter.self],
93+
indentationWidth: indentationWidth
94+
)
95+
96+
assertMacroExpansion(
97+
"""
98+
@constantOne
99+
var x /// hello
100+
""",
101+
expandedSource: """
102+
var x /** hello*/ {
103+
get {
104+
return 1
105+
}
106+
}
107+
""",
108+
macros: ["constantOne": ConstantOneGetter.self],
109+
indentationWidth: indentationWidth
110+
)
111+
}
112+
113+
func testAccessorOnVariableDeclWithTrailingLineCommentAndAccessorBlock() {
114+
assertMacroExpansion(
115+
"""
116+
@constantOne
117+
var x: Int { // hello
118+
1
119+
}
120+
""",
121+
expandedSource: """
122+
var x: Int { // hello
123+
get {
124+
1
125+
}
126+
get {
127+
return 1
128+
}
129+
}
130+
""",
131+
macros: ["constantOne": ConstantOneGetter.self],
132+
indentationWidth: indentationWidth
133+
)
134+
}
135+
47136
func testAccessorOnVariableDeclWithExistingGetter() {
48137
assertMacroExpansion(
49138
"""

0 commit comments

Comments
 (0)