@@ -22,6 +22,7 @@ public enum MacroRole {
2222 case peer
2323 case conformance
2424 case codeItem
25+ case `extension`
2526}
2627
2728extension MacroRole {
@@ -35,6 +36,7 @@ extension MacroRole {
3536 case . peer: return " PeerMacro "
3637 case . conformance: return " ConformanceMacro "
3738 case . codeItem: return " CodeItemMacro "
39+ case . extension: return " ExtensionMacro "
3840 }
3941 }
4042}
@@ -45,6 +47,7 @@ private enum MacroExpansionError: Error, CustomStringConvertible {
4547 case parentDeclGroupNil
4648 case declarationNotDeclGroup
4749 case declarationNotIdentified
50+ case noExtendedTypeSyntax
4851 case noFreestandingMacroRoles( Macro . Type )
4952
5053 var description : String {
@@ -61,6 +64,9 @@ private enum MacroExpansionError: Error, CustomStringConvertible {
6164 case . declarationNotIdentified:
6265 return " declaration is not a 'Identified' syntax "
6366
67+ case . noExtendedTypeSyntax:
68+ return " no extended type for extension macro "
69+
6470 case . noFreestandingMacroRoles( let type) :
6571 return " macro implementation type ' \( type) ' does not conform to any freestanding macro protocol "
6672
@@ -113,7 +119,7 @@ public func expandFreestandingMacro(
113119 let rewritten = try codeItemMacroDef. expansion ( of: node, in: context)
114120 expandedSyntax = Syntax ( CodeBlockItemListSyntax ( rewritten) )
115121
116- case ( . accessor, _) , ( . memberAttribute, _) , ( . member, _) , ( . peer, _) , ( . conformance, _) , ( . expression, _) , ( . declaration, _) ,
122+ case ( . accessor, _) , ( . memberAttribute, _) , ( . member, _) , ( . peer, _) , ( . conformance, _) , ( . extension , _ ) , ( . expression, _) , ( . declaration, _) ,
117123 ( . codeItem, _) :
118124 throw MacroExpansionError . unmatchedMacroRole ( definition, macroRole)
119125 }
@@ -178,6 +184,7 @@ public func expandAttachedMacroWithoutCollapsing<Context: MacroExpansionContext>
178184 attributeNode: AttributeSyntax ,
179185 declarationNode: DeclSyntax ,
180186 parentDeclNode: DeclSyntax ? ,
187+ extendedType: TypeSyntax ? ,
181188 in context: Context
182189) -> [ String ] ? {
183190 do {
@@ -295,6 +302,39 @@ public func expandAttachedMacroWithoutCollapsing<Context: MacroExpansionContext>
295302 return " extension \( typeName) : \( protocolName) \( whereClause) {} "
296303 }
297304
305+ case ( let attachedMacro as ExtensionMacro . Type , . extension) :
306+ guard let declGroup = declarationNode. asProtocol ( DeclGroupSyntax . self) else {
307+ // Compiler error: type mismatch.
308+ throw MacroExpansionError . declarationNotDeclGroup
309+ }
310+
311+ guard let extendedType = extendedType else {
312+ throw MacroExpansionError . noExtendedTypeSyntax
313+ }
314+
315+ // Local function to expand an extension macro once we've opened up
316+ // the existential.
317+ func expandExtensionMacro(
318+ _ node: some DeclGroupSyntax
319+ ) throws -> [ ExtensionDeclSyntax ] {
320+ return try attachedMacro. expansion (
321+ of: attributeNode,
322+ attachedTo: node,
323+ providingExtensionsOf: extendedType,
324+ in: context
325+ )
326+ }
327+
328+ let extensions = try _openExistential (
329+ declGroup,
330+ do: expandExtensionMacro
331+ )
332+
333+ // Form a buffer of peer declarations to return to the caller.
334+ return extensions. map {
335+ $0. formattedExpansion ( definition. formatMode)
336+ }
337+
298338 default :
299339 throw MacroExpansionError . unmatchedMacroRole ( definition, macroRole)
300340 }
@@ -323,6 +363,7 @@ public func expandAttachedMacro<Context: MacroExpansionContext>(
323363 attributeNode: AttributeSyntax ,
324364 declarationNode: DeclSyntax ,
325365 parentDeclNode: DeclSyntax ? ,
366+ extendedType: TypeSyntax ? ,
326367 in context: Context
327368) -> String ? {
328369 let expandedSources = expandAttachedMacroWithoutCollapsing (
@@ -331,6 +372,7 @@ public func expandAttachedMacro<Context: MacroExpansionContext>(
331372 attributeNode: attributeNode,
332373 declarationNode: declarationNode,
333374 parentDeclNode: parentDeclNode,
375+ extendedType: extendedType,
334376 in: context
335377 )
336378 return expandedSources. map {
0 commit comments