Skip to content

Commit 609a379

Browse files
committed
[Macros] Pass a list of protocols to conform to when expanding an extension
macro.
1 parent d20f066 commit 609a379

File tree

8 files changed

+32
-4
lines changed

8 files changed

+32
-4
lines changed

Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,16 @@ extension CompilerPluginMessageHandler {
122122
expandingSyntax: expandingSyntax
123123
)
124124

125-
case .expandAttachedMacro(let macro, let macroRole, let discriminator, let attributeSyntax, let declSyntax, let parentDeclSyntax, let extendedTypeSyntax):
125+
case .expandAttachedMacro(let macro, let macroRole, let discriminator, let attributeSyntax, let declSyntax, let parentDeclSyntax, let extendedTypeSyntax, let conformanceListSyntax):
126126
try expandAttachedMacro(
127127
macro: macro,
128128
macroRole: macroRole,
129129
discriminator: discriminator,
130130
attributeSyntax: attributeSyntax,
131131
declSyntax: declSyntax,
132132
parentDeclSyntax: parentDeclSyntax,
133-
extendedTypeSyntax: extendedTypeSyntax
133+
extendedTypeSyntax: extendedTypeSyntax,
134+
conformanceListSyntax: conformanceListSyntax
134135
)
135136

136137
case .loadPluginLibrary(let libraryPath, let moduleName):

Sources/SwiftCompilerPluginMessageHandling/Macros.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ extension CompilerPluginMessageHandler {
8787
attributeSyntax: PluginMessage.Syntax,
8888
declSyntax: PluginMessage.Syntax,
8989
parentDeclSyntax: PluginMessage.Syntax?,
90-
extendedTypeSyntax: PluginMessage.Syntax?
90+
extendedTypeSyntax: PluginMessage.Syntax?,
91+
conformanceListSyntax: PluginMessage.Syntax?
9192
) throws {
9293
let sourceManager = SourceManager()
9394
let context = PluginMacroExpansionContext(
@@ -104,6 +105,10 @@ extension CompilerPluginMessageHandler {
104105
let extendedType = extendedTypeSyntax.map {
105106
sourceManager.add($0).cast(TypeSyntax.self)
106107
}
108+
let conformanceList = conformanceListSyntax.map {
109+
let placeholderStruct = sourceManager.add($0).cast(StructDeclSyntax.self)
110+
return placeholderStruct.inheritanceClause!.inheritedTypeCollection
111+
}
107112

108113
// TODO: Make this a 'String?' and remove non-'hasExpandMacroResult' branches.
109114
let expandedSources: [String]?
@@ -120,6 +125,7 @@ extension CompilerPluginMessageHandler {
120125
declarationNode: declarationNode,
121126
parentDeclNode: parentDeclNode,
122127
extendedType: extendedType,
128+
conformanceList: conformanceList,
123129
in: context
124130
)
125131
if let expansions, hostCapability.hasExpandMacroResult {

Sources/SwiftCompilerPluginMessageHandling/PluginMessages.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
attributeSyntax: PluginMessage.Syntax,
3535
declSyntax: PluginMessage.Syntax,
3636
parentDeclSyntax: PluginMessage.Syntax?,
37-
extendedTypeSyntax: PluginMessage.Syntax?
37+
extendedTypeSyntax: PluginMessage.Syntax?,
38+
conformanceListSyntax: PluginMessage.Syntax?
3839
)
3940

4041
/// Optionally implemented message to load a dynamic link library.

Sources/SwiftSyntaxMacroExpansion/MacroExpansion.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ public func expandAttachedMacroWithoutCollapsing<Context: MacroExpansionContext>
185185
declarationNode: DeclSyntax,
186186
parentDeclNode: DeclSyntax?,
187187
extendedType: TypeSyntax?,
188+
conformanceList: InheritedTypeListSyntax?,
188189
in context: Context
189190
) -> [String]? {
190191
do {
@@ -276,6 +277,8 @@ public func expandAttachedMacroWithoutCollapsing<Context: MacroExpansionContext>
276277
throw MacroExpansionError.noExtendedTypeSyntax
277278
}
278279

280+
let protocols = conformanceList?.map(\.typeName) ?? []
281+
279282
// Local function to expand an extension macro once we've opened up
280283
// the existential.
281284
func expandExtensionMacro(
@@ -285,6 +288,7 @@ public func expandAttachedMacroWithoutCollapsing<Context: MacroExpansionContext>
285288
of: attributeNode,
286289
attachedTo: node,
287290
providingExtensionsOf: extendedType,
291+
conformingTo: protocols,
288292
in: context
289293
)
290294
}
@@ -328,6 +332,7 @@ public func expandAttachedMacro<Context: MacroExpansionContext>(
328332
declarationNode: DeclSyntax,
329333
parentDeclNode: DeclSyntax?,
330334
extendedType: TypeSyntax?,
335+
conformanceList: InheritedTypeListSyntax?,
331336
in context: Context
332337
) -> String? {
333338
let expandedSources = expandAttachedMacroWithoutCollapsing(
@@ -337,6 +342,7 @@ public func expandAttachedMacro<Context: MacroExpansionContext>(
337342
declarationNode: declarationNode,
338343
parentDeclNode: parentDeclNode,
339344
extendedType: extendedType,
345+
conformanceList: conformanceList,
340346
in: context
341347
)
342348
return expandedSources.map {

Sources/SwiftSyntaxMacros/MacroProtocols/ConformanceMacro.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ extension ConformanceMacro {
3737
of node: AttributeSyntax,
3838
attachedTo declaration: some DeclGroupSyntax,
3939
providingExtensionsOf type: some TypeSyntaxProtocol,
40+
conformingTo protocols: [TypeSyntax],
4041
in context: some MacroExpansionContext
4142
) throws -> [ExtensionDeclSyntax] {
4243

Sources/SwiftSyntaxMacros/MacroProtocols/ExtensionMacro.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public protocol ExtensionMacro: AttachedMacro {
2121
/// - node: The custom attribute describing the attached macro.
2222
/// - declaration: The declaration the macro attribute is attached to.
2323
/// - type: The type to provide extensions of.
24+
/// - protocols: The list of protocols to add conformances to. These will
25+
/// always be protocols that `type` does not already state a conformance
26+
/// to.
2427
/// - context: The context in which to perform the macro expansion.
2528
///
2629
/// - Returns: the set of extension declarations introduced by the macro,
@@ -30,6 +33,7 @@ public protocol ExtensionMacro: AttachedMacro {
3033
of node: AttributeSyntax,
3134
attachedTo declaration: some DeclGroupSyntax,
3235
providingExtensionsOf type: some TypeSyntaxProtocol,
36+
conformingTo protocols: [TypeSyntax],
3337
in context: some MacroExpansionContext
3438
) throws -> [ExtensionDeclSyntax]
3539
}

Sources/SwiftSyntaxMacros/MacroSystem.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,14 @@ extension MacroApplication {
422422
let extensionMacroAttrs = getMacroAttributes(attachedTo: decl.as(DeclSyntax.self)!, ofType: ExtensionMacro.Type.self)
423423
for (attribute, extensionMacro) in extensionMacroAttrs {
424424
do {
425+
// FIXME: We need a way for unit tests of extension macros to
426+
// specify protocols already stated in source (e.g. as arguments
427+
// to `assertMacroExpansion`).
425428
let newExtensions = try extensionMacro.expansion(
426429
of: attribute,
427430
attachedTo: decl,
428431
providingExtensionsOf: extendedType,
432+
conformingTo: [],
429433
in: context
430434
)
431435

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,13 @@ public struct SendableExtensionMacro: ExtensionMacro {
687687
of node: AttributeSyntax,
688688
attachedTo: some DeclGroupSyntax,
689689
providingExtensionsOf type: some TypeSyntaxProtocol,
690+
conformingTo protocols: [TypeSyntax],
690691
in context: some MacroExpansionContext
691692
) throws -> [ExtensionDeclSyntax] {
693+
if protocols.isEmpty {
694+
return []
695+
}
696+
692697
let sendableExtension: DeclSyntax =
693698
"""
694699
extension \(type.trimmed): Sendable {}

0 commit comments

Comments
 (0)