@@ -23,6 +23,7 @@ extension SyntaxProtocol {
23
23
/// Expand all uses of the given set of macros within this syntax node.
24
24
public func expand(
25
25
macros: [ String : Macro . Type ] ,
26
+ conformsTo conformanceMap: [ String : InheritedTypeListSyntax ] ,
26
27
in context: some MacroExpansionContext ,
27
28
indentationWidth: Trivia ? = nil
28
29
) -> Syntax {
@@ -31,6 +32,9 @@ extension SyntaxProtocol {
31
32
for (macroName, macroType) in macros {
32
33
try ! system. add ( macroType, name: macroName)
33
34
}
35
+ for (macroName, conformanceList) in conformanceMap {
36
+ try ! system. add ( conformanceList, name: macroName)
37
+ }
34
38
35
39
let applier = MacroApplication (
36
40
macroSystem: system,
@@ -316,6 +320,7 @@ private func expandExtensionMacro(
316
320
definition: ExtensionMacro . Type ,
317
321
attributeNode: AttributeSyntax ,
318
322
attachedTo: DeclSyntax ,
323
+ conformanceList: InheritedTypeListSyntax ? ,
319
324
in context: some MacroExpansionContext ,
320
325
indentationWidth: Trivia
321
326
) throws -> CodeBlockItemListSyntax ? {
@@ -336,7 +341,7 @@ private func expandExtensionMacro(
336
341
declarationNode: attachedTo. detach ( in: context) ,
337
342
parentDeclNode: nil ,
338
343
extendedType: extendedType. detach ( in: context) ,
339
- conformanceList: [ ] ,
344
+ conformanceList: conformanceList ?? [ ] ,
340
345
in: context,
341
346
indentationWidth: indentationWidth
342
347
)
@@ -355,11 +360,14 @@ private func expandExtensionMacro(
355
360
enum MacroSystemError : Error {
356
361
/// Indicates that a macro with the given name has already been defined.
357
362
case alreadyDefined( new: Macro . Type , existing: Macro . Type )
363
+ /// Indicates that protocol conformances for a macro with the given name has already been defined.
364
+ case alreadyConforming( new: InheritedTypeListSyntax , existing: InheritedTypeListSyntax )
358
365
}
359
366
360
367
/// A system of known macros that can be expanded syntactically
361
368
struct MacroSystem {
362
369
var macros : [ String : Macro . Type ] = [ : ]
370
+ var conformanceMap : [ String : InheritedTypeListSyntax ] = [ : ]
363
371
364
372
/// Create an empty macro system.
365
373
init ( ) { }
@@ -375,10 +383,26 @@ struct MacroSystem {
375
383
macros [ name] = macro
376
384
}
377
385
386
+ /// Add protocol conformances for a macro to the system.
387
+ ///
388
+ /// Throws an error if there is already conformances for a macro with this name.
389
+ mutating func add( _ conformanceList: InheritedTypeListSyntax , name: String ) throws {
390
+ if let knownConformanceList = conformanceMap [ name] {
391
+ throw MacroSystemError . alreadyConforming ( new: conformanceList, existing: knownConformanceList)
392
+ }
393
+
394
+ conformanceMap [ name] = conformanceList
395
+ }
396
+
378
397
/// Look for a macro with the given name.
379
398
func lookup( _ macroName: String ) -> Macro . Type ? {
380
399
return macros [ macroName]
381
400
}
401
+
402
+ /// Look for protocol conformances of a macro with the given name.
403
+ func conformaces( forMacro macroName: String ) -> InheritedTypeListSyntax ? {
404
+ return conformanceMap [ macroName]
405
+ }
382
406
}
383
407
384
408
// MARK: - MacroApplication
@@ -716,12 +740,13 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
716
740
// MARK: Attached macro expansions.
717
741
718
742
extension MacroApplication {
719
- /// Get pairs of a macro attribute and the macro definition attached to `decl`.
743
+ /// Get macro attribute, the macro definition and optional
744
+ /// conformance protocols list attached to `decl`.
720
745
///
721
746
/// The macros must be registered in `macroSystem`.
722
747
private func macroAttributes(
723
748
attachedTo decl: DeclSyntax
724
- ) -> [ ( attributeNode: AttributeSyntax , definition: Macro . Type ) ] {
749
+ ) -> [ ( attributeNode: AttributeSyntax , definition: Macro . Type , conformanceList : InheritedTypeListSyntax ? ) ] {
725
750
guard let attributedNode = decl. asProtocol ( WithAttributesSyntax . self) else {
726
751
return [ ]
727
752
}
@@ -734,22 +759,22 @@ extension MacroApplication {
734
759
return nil
735
760
}
736
761
737
- return ( attribute, macro)
762
+ return ( attribute, macro, macroSystem . conformaces ( forMacro : attributeName ) )
738
763
}
739
764
}
740
765
741
- /// Get pairs of a macro attribute and the macro definition attached to `decl`
742
- /// matching `ofType` macro type.
766
+ /// Get macro attribute, the macro definition and optional conformance
767
+ /// protocols list attached to `decl` matching `ofType` macro type.
743
768
///
744
769
/// The macros must be registered in `macroSystem`.
745
770
private func macroAttributes< MacroType> (
746
771
attachedTo decl: DeclSyntax ,
747
772
ofType: MacroType . Type
748
- ) -> [ ( attributeNode: AttributeSyntax , definition: MacroType ) ] {
773
+ ) -> [ ( attributeNode: AttributeSyntax , definition: MacroType , conformanceList : InheritedTypeListSyntax ? ) ] {
749
774
return macroAttributes ( attachedTo: decl)
750
- . compactMap { ( attributeNode: AttributeSyntax , definition: Macro . Type ) in
775
+ . compactMap { ( attributeNode: AttributeSyntax , definition: Macro . Type , conformanceList : InheritedTypeListSyntax ? ) in
751
776
if let macroType = definition as? MacroType {
752
- return ( attributeNode, macroType)
777
+ return ( attributeNode, macroType, conformanceList )
753
778
} else {
754
779
return nil
755
780
}
@@ -765,13 +790,13 @@ extension MacroApplication {
765
790
> (
766
791
attachedTo decl: DeclSyntax ,
767
792
ofType: MacroType . Type ,
768
- expandMacro: ( _ attributeNode: AttributeSyntax , _ definition: MacroType ) throws -> ExpanedNodeCollection ?
793
+ expandMacro: ( _ attributeNode: AttributeSyntax , _ definition: MacroType , _ conformanceList : InheritedTypeListSyntax ? ) throws -> ExpanedNodeCollection ?
769
794
) -> [ ExpandedNode ] {
770
795
var result : [ ExpandedNode ] = [ ]
771
796
772
797
for macroAttribute in macroAttributes ( attachedTo: decl, ofType: ofType) {
773
798
do {
774
- if let expanded = try expandMacro ( macroAttribute. attributeNode, macroAttribute. definition) {
799
+ if let expanded = try expandMacro ( macroAttribute. attributeNode, macroAttribute. definition, macroAttribute . conformanceList ) {
775
800
result += expanded
776
801
}
777
802
} catch {
@@ -789,7 +814,7 @@ extension MacroApplication {
789
814
///
790
815
/// - Returns: The macro-synthesized peers
791
816
private func expandMemberDeclPeers( of decl: DeclSyntax ) -> [ MemberBlockItemSyntax ] {
792
- return expandMacros ( attachedTo: decl, ofType: PeerMacro . Type. self) { attributeNode, definition in
817
+ return expandMacros ( attachedTo: decl, ofType: PeerMacro . Type. self) { attributeNode, definition, conformanceList in
793
818
return try expandPeerMacroMember (
794
819
definition: definition,
795
820
attributeNode: attributeNode,
@@ -809,7 +834,7 @@ extension MacroApplication {
809
834
///
810
835
/// - Returns: The macro-synthesized peers
811
836
private func expandCodeBlockPeers( of decl: DeclSyntax ) -> [ CodeBlockItemSyntax ] {
812
- return expandMacros ( attachedTo: decl, ofType: PeerMacro . Type. self) { attributeNode, definition in
837
+ return expandMacros ( attachedTo: decl, ofType: PeerMacro . Type. self) { attributeNode, definition, conformanceList in
813
838
return try expandPeerMacroCodeItem (
814
839
definition: definition,
815
840
attributeNode: attributeNode,
@@ -824,11 +849,12 @@ extension MacroApplication {
824
849
///
825
850
/// - Returns: The macro-synthesized extensions
826
851
private func expandExtensions( of decl: DeclSyntax ) -> [ CodeBlockItemSyntax ] {
827
- return expandMacros ( attachedTo: decl, ofType: ExtensionMacro . Type. self) { attributeNode, definition in
852
+ return expandMacros ( attachedTo: decl, ofType: ExtensionMacro . Type. self) { attributeNode, definition, conformanceList in
828
853
return try expandExtensionMacro (
829
854
definition: definition,
830
855
attributeNode: attributeNode,
831
856
attachedTo: decl,
857
+ conformanceList: conformanceList,
832
858
in: context,
833
859
indentationWidth: indentationWidth
834
860
)
@@ -837,7 +863,7 @@ extension MacroApplication {
837
863
838
864
/// Expand all 'member' macros attached to `decl`.
839
865
private func expandMembers( of decl: DeclSyntax ) -> [ MemberBlockItemSyntax ] {
840
- return expandMacros ( attachedTo: decl, ofType: MemberMacro . Type. self) { attributeNode, definition in
866
+ return expandMacros ( attachedTo: decl, ofType: MemberMacro . Type. self) { attributeNode, definition, conformanceList in
841
867
return try expandMemberMacro (
842
868
definition: definition,
843
869
attributeNode: attributeNode,
@@ -857,7 +883,7 @@ extension MacroApplication {
857
883
of decl: DeclSyntax ,
858
884
parentDecl: DeclSyntax
859
885
) -> [ AttributeListSyntax . Element ] {
860
- return expandMacros ( attachedTo: parentDecl, ofType: MemberAttributeMacro . Type. self) { attributeNode, definition in
886
+ return expandMacros ( attachedTo: parentDecl, ofType: MemberAttributeMacro . Type. self) { attributeNode, definition, conformanceList in
861
887
return try expandMemberAttributeMacro (
862
888
definition: definition,
863
889
attributeNode: attributeNode,
0 commit comments