Skip to content

Commit 5d77ef4

Browse files
committed
[MacroSystem] Expand extension macros.
1 parent aa6cc4a commit 5d77ef4

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

Sources/SwiftSyntaxMacros/MacroSystem.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
115115
|| macro is MemberMacro.Type
116116
|| macro is AccessorMacro.Type
117117
|| macro is MemberAttributeMacro.Type
118-
|| macro is ConformanceMacro.Type)
118+
|| macro is ConformanceMacro.Type
119+
|| macro is ExtensionMacro.Type)
119120
}
120121

121122
if newAttributes.isEmpty {
@@ -438,6 +439,20 @@ extension MacroApplication {
438439
}
439440
}
440441

442+
let extensionMacroAttrs = getMacroAttributes(attachedTo: decl.as(DeclSyntax.self)!, ofType: ExtensionMacro.Type.self)
443+
let extendedTypeSyntax = TypeSyntax("\(extendedType.trimmed)")
444+
for (attribute, extensionMacro) in extensionMacroAttrs {
445+
do {
446+
let newExtensions = try extensionMacro.expansion(of: attribute,
447+
attachedTo: decl,
448+
providingExtensionsOf: extendedTypeSyntax,
449+
in: context)
450+
extensions.append(contentsOf: newExtensions.map(DeclSyntax.init))
451+
} catch {
452+
context.addDiagnostics(from: error, node: attribute)
453+
}
454+
}
455+
441456
return extensions
442457
}
443458

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,26 @@ public struct SendableConformanceMacro: ConformanceMacro {
682682
}
683683
}
684684

685+
public struct SendableExtensionMacro: ExtensionMacro {
686+
public static func expansion(
687+
of node: AttributeSyntax,
688+
attachedTo: some DeclGroupSyntax,
689+
providingExtensionsOf type: some TypeSyntaxProtocol,
690+
in context: some MacroExpansionContext
691+
) throws -> [ExtensionDeclSyntax] {
692+
let sendableExtension: DeclSyntax =
693+
"""
694+
extension \(type.trimmed): Sendable {}
695+
"""
696+
697+
guard let extensionDecl = sendableExtension.as(ExtensionDeclSyntax.self) else {
698+
return []
699+
}
700+
701+
return [extensionDecl]
702+
}
703+
}
704+
685705
public struct DeclsFromStringsMacroNoAttrs: DeclarationMacro {
686706
public static var propagateFreestandingMacroAttributes: Bool { false }
687707
public static var propagateFreestandingMacroModifiers: Bool { false }
@@ -726,6 +746,7 @@ public let testMacros: [String: Macro.Type] = [
726746
"customTypeWrapper": CustomTypeWrapperMacro.self,
727747
"unwrap": UnwrapMacro.self,
728748
"AddSendable": SendableConformanceMacro.self,
749+
"AddSendableExtension": SendableExtensionMacro.self,
729750
]
730751

731752
final class MacroSystemTests: XCTestCase {
@@ -1196,4 +1217,23 @@ final class MacroSystemTests: XCTestCase {
11961217
indentationWidth: indentationWidth
11971218
)
11981219
}
1220+
1221+
func testExtensionExpansion() {
1222+
assertMacroExpansion(
1223+
"""
1224+
@AddSendableExtension
1225+
struct MyType {
1226+
}
1227+
""",
1228+
expandedSource: """
1229+
1230+
struct MyType {
1231+
}
1232+
extension MyType: Sendable {
1233+
}
1234+
""",
1235+
macros: testMacros,
1236+
indentationWidth: indentationWidth
1237+
)
1238+
}
11991239
}

0 commit comments

Comments
 (0)