Skip to content

Commit 4659349

Browse files
committed
MacroSystem should qualify nested types when expanding extension macros
Resolves rdar://119850970.
1 parent 184930a commit 4659349

File tree

2 files changed

+76
-14
lines changed

2 files changed

+76
-14
lines changed

Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,7 @@ private func expandExtensionMacro(
319319
in context: some MacroExpansionContext,
320320
indentationWidth: Trivia
321321
) throws -> CodeBlockItemListSyntax? {
322-
let extendedType: TypeSyntax
323-
if let identified = attachedTo.asProtocol(NamedDeclSyntax.self) {
324-
extendedType = "\(identified.name.trimmed)"
325-
} else if let ext = attachedTo.as(ExtensionDeclSyntax.self) {
326-
extendedType = "\(ext.extendedType.trimmed)"
327-
} else {
322+
guard let extendedType = attachedTo.syntacticQualifiedTypeContext else {
328323
return nil
329324
}
330325

@@ -1299,3 +1294,25 @@ private extension AccessorDeclSyntax {
12991294
return accessorSpecifier.tokenKind == .keyword(.get) || accessorSpecifier.tokenKind == .keyword(.set)
13001295
}
13011296
}
1297+
1298+
private extension SyntaxProtocol {
1299+
/// Retrieve the qualified type for the nearest extension or name decl.
1300+
///
1301+
/// For example, for `struct Foo { struct Bar {} }`, calling this on the
1302+
/// inner struct (`Bar`) will return `Foo.Bar`.
1303+
var syntacticQualifiedTypeContext: TypeSyntax? {
1304+
if let ext = self.as(ExtensionDeclSyntax.self) {
1305+
// Don't handle nested 'extension' cases - they are invalid anyway.
1306+
return ext.extendedType.trimmed
1307+
}
1308+
1309+
let base = self.parent?.syntacticQualifiedTypeContext
1310+
if let named = self.asProtocol(NamedDeclSyntax.self) {
1311+
if let base = base {
1312+
return TypeSyntax(MemberTypeSyntax(baseType: base, name: named.name.trimmed))
1313+
}
1314+
return TypeSyntax(IdentifierTypeSyntax(name: named.name.trimmed))
1315+
}
1316+
return base
1317+
}
1318+
}

Tests/SwiftSyntaxMacroExpansionTest/ExtensionMacroTests.swift

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,10 @@ final class ExtensionMacroTests: XCTestCase {
7070
assertMacroExpansion(
7171
"""
7272
@AddSendableExtension
73-
struct MyType {
74-
}
73+
struct MyType {}
7574
""",
7675
expandedSource: """
77-
78-
struct MyType {
79-
}
76+
struct MyType {}
8077
8178
extension MyType: Sendable {
8279
}
@@ -89,17 +86,65 @@ final class ExtensionMacroTests: XCTestCase {
8986
"""
9087
struct Wrapper {
9188
@AddSendableExtension
92-
struct MyType {
89+
struct MyType {}
90+
}
91+
""",
92+
expandedSource: """
93+
struct Wrapper {
94+
struct MyType {}
95+
}
96+
97+
extension Wrapper.MyType: Sendable {
9398
}
99+
""",
100+
macros: ["AddSendableExtension": SendableExtensionMacro.self],
101+
indentationWidth: indentationWidth
102+
)
103+
104+
assertMacroExpansion(
105+
"""
106+
struct Wrapper {
107+
struct AnotherWrapper {}
108+
}
109+
extension Wrapper.AnotherWrapper {
110+
@AddSendableExtension
111+
struct MyType {}
94112
}
95113
""",
96114
expandedSource: """
97115
struct Wrapper {
98-
struct MyType {
116+
struct AnotherWrapper {}
117+
}
118+
extension Wrapper.AnotherWrapper {
119+
struct MyType {}
120+
}
121+
122+
extension Wrapper.AnotherWrapper.MyType: Sendable {
123+
}
124+
""",
125+
macros: ["AddSendableExtension": SendableExtensionMacro.self],
126+
indentationWidth: indentationWidth
127+
)
128+
129+
assertMacroExpansion(
130+
"""
131+
struct Wrapper {}
132+
extension Wrapper {
133+
struct AnotherWrapper {
134+
@AddSendableExtension
135+
struct MyType {}
136+
}
137+
}
138+
""",
139+
expandedSource: """
140+
struct Wrapper {}
141+
extension Wrapper {
142+
struct AnotherWrapper {
143+
struct MyType {}
99144
}
100145
}
101146
102-
extension MyType: Sendable {
147+
extension Wrapper.AnotherWrapper.MyType: Sendable {
103148
}
104149
""",
105150
macros: ["AddSendableExtension": SendableExtensionMacro.self],

0 commit comments

Comments
 (0)