@@ -178,14 +178,23 @@ class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
178
178
let newItem = visit ( item. item)
179
179
newItems. append ( item. with ( \. item, newItem) )
180
180
181
- // Expand any peer declarations triggered by macros used as attributes.
181
+ // Expand any peer declarations or conformances triggered by macros used
182
+ // as attributes.
182
183
if case let . decl( decl) = item. item {
183
184
let peers = expandPeers ( of: decl)
184
185
newItems. append (
185
186
contentsOf: peers. map {
186
187
newDecl in CodeBlockItemSyntax ( item: . decl( newDecl) )
187
188
}
188
189
)
190
+
191
+ if let declGroup = decl. asProtocol ( DeclGroupSyntax . self) {
192
+ newItems. append (
193
+ contentsOf: expandConformances ( of: declGroup) . map {
194
+ newDecl in CodeBlockItemSyntax ( item: . decl( newDecl) )
195
+ }
196
+ )
197
+ }
189
198
}
190
199
}
191
200
@@ -394,6 +403,43 @@ extension MacroApplication {
394
403
return peers
395
404
}
396
405
406
+ // If any of the custom attributes associated with the given declaration
407
+ // refer to conformance macros, expand them and return the resulting
408
+ // set of extension declarations.
409
+ private func expandConformances( of decl: DeclGroupSyntax ) -> [ DeclSyntax ] {
410
+ let identifier : String
411
+ if let identified = decl. asProtocol ( IdentifiedDeclSyntax . self) {
412
+ identifier = identified. identifier. text
413
+ } else if let ext = decl. as ( ExtensionDeclSyntax . self) {
414
+ identifier = ext. extendedType. trimmedDescription
415
+ } else {
416
+ return [ ]
417
+ }
418
+
419
+ var extensions : [ DeclSyntax ] = [ ]
420
+ let macroAttributes = getMacroAttributes ( attachedTo: decl. as ( DeclSyntax . self) !, ofType: ConformanceMacro . Type. self)
421
+ for (attribute, conformanceMacro) in macroAttributes {
422
+ do {
423
+ let newConformances = try conformanceMacro. expansion ( of: attribute, providingConformancesOf: decl, in: context)
424
+
425
+ for (type, whereClause) in newConformances {
426
+ var ext : DeclSyntax = """
427
+ extension \( raw: identifier) : \( type) { }
428
+ """
429
+ if let whereClause {
430
+ ext = DeclSyntax ( ( ext. as ( ExtensionDeclSyntax . self) ) !. with ( \. genericWhereClause, whereClause) )
431
+ }
432
+
433
+ extensions. append ( DeclSyntax ( ext) )
434
+ }
435
+ } catch {
436
+ context. addDiagnostics ( from: error, node: attribute)
437
+ }
438
+ }
439
+
440
+ return extensions
441
+ }
442
+
397
443
/// Expands any attached custom attributes that refer to member declaration macros,
398
444
/// and returns result of adding those members to the given declaration.
399
445
private func expandMembers< Decl: DeclGroupSyntax & DeclSyntaxProtocol > (
0 commit comments