@@ -25,24 +25,26 @@ private enum MacroExpansionError: String, Error, CustomStringConvertible {
25
25
///
26
26
/// - Parameters:
27
27
/// - definition: a type conforms to one of freestanding `Macro` protocol.
28
+ /// - macroRole: indicates which `Macro` protocol expansion should be performed
28
29
/// - node: macro expansion syntax node (e.g. `#macroName(argument)`).
29
30
/// - in: context of the expansion.
30
31
/// - Returns: expanded source text. Upon failure (i.e. `defintion.expansion()`
31
32
/// throws) returns `nil`, and the diagnostics representing the `Error` are
32
33
/// guaranteed to be added to context.
33
34
public func expandFreestandingMacro(
34
35
definition: Macro . Type ,
36
+ macroRole: MacroRole ,
35
37
node: FreestandingMacroExpansionSyntax ,
36
38
in context: some MacroExpansionContext
37
39
) -> String ? {
38
40
do {
39
41
func _expand( node: some FreestandingMacroExpansionSyntax ) throws -> String {
40
42
let expandedSyntax : Syntax
41
- switch definition {
42
- case let exprMacroDef as ExpressionMacro . Type :
43
+ switch ( macroRole , definition) {
44
+ case ( . expression , let exprMacroDef as ExpressionMacro . Type ) :
43
45
expandedSyntax = try Syntax ( exprMacroDef. expansion ( of: node, in: context) )
44
46
45
- case let declMacroDef as DeclarationMacro . Type :
47
+ case ( . declaration , let declMacroDef as DeclarationMacro . Type ) :
46
48
var rewritten = try declMacroDef. expansion ( of: node, in: context)
47
49
// Copy attributes and modifiers to the generated decls.
48
50
if let expansionDecl = node. as ( MacroExpansionDeclSyntax . self) {
@@ -60,12 +62,15 @@ public func expandFreestandingMacro(
60
62
)
61
63
)
62
64
63
- case let codeItemMacroDef as CodeItemMacro . Type :
65
+ case ( . codeItem , let codeItemMacroDef as CodeItemMacro . Type ) :
64
66
let rewritten = try codeItemMacroDef. expansion ( of: node, in: context)
65
67
expandedSyntax = Syntax ( CodeBlockItemListSyntax ( rewritten) )
66
68
67
- default :
69
+ case ( . expression , _ ) , ( . declaration , _ ) , ( . codeItem , _ ) :
68
70
throw MacroExpansionError . unmathedMacroRole
71
+
72
+ case ( . accessor, _) , ( . memberAttribute, _) , ( . member, _) , ( . peer, _) , ( . conformance, _) , ( . codeItem, _) :
73
+ fatalError ( " macro role \( macroRole) is not a freestanding macro " )
69
74
}
70
75
return expandedSyntax. formattedExpansion ( definition. formatMode)
71
76
}
@@ -76,6 +81,39 @@ public func expandFreestandingMacro(
76
81
}
77
82
}
78
83
84
+ /// Try to infer the freestanding macro role from the type definition itself.
85
+ ///
86
+ /// This is a workaround for older compilers with a newer plugin
87
+ public func inferFreestandingMacroRole( definition: Macro . Type ) throws -> MacroRole {
88
+ switch definition {
89
+ case is ExpressionMacro . Type : return . expression
90
+ case is DeclarationMacro . Type : return . declaration
91
+ case is CodeItemMacro . Type : return . codeItem
92
+
93
+ default :
94
+ throw MacroExpansionError . unmathedMacroRole
95
+ }
96
+ }
97
+
98
+ @available ( * , deprecated, message: " pass a macro role, please! " )
99
+ public func expandFreestandingMacro(
100
+ definition: Macro . Type ,
101
+ node: FreestandingMacroExpansionSyntax ,
102
+ in context: some MacroExpansionContext
103
+ ) -> String ? {
104
+ do {
105
+ return expandFreestandingMacro (
106
+ definition: definition,
107
+ macroRole: try inferFreestandingMacroRole ( definition: definition) ,
108
+ node: node,
109
+ in: context
110
+ )
111
+ } catch {
112
+ context. addDiagnostics ( from: error, node: node)
113
+ return nil
114
+ }
115
+ }
116
+
79
117
/// Expand `@attached(XXX)` macros.
80
118
///
81
119
/// - Parameters:
0 commit comments