@@ -18,6 +18,7 @@ enum MacroExpanderError: DiagnosticMessage {
18
18
case undefined
19
19
case definitionNotMacroExpansion
20
20
case nonParameterReference( TokenSyntax )
21
+ case nonTypeReference( TypeSyntax )
21
22
case nonLiteralOrParameter( ExprSyntax )
22
23
23
24
var message : String {
@@ -31,6 +32,9 @@ enum MacroExpanderError: DiagnosticMessage {
31
32
case . nonParameterReference( let name) :
32
33
return " reference to value ' \( name. text) ' that is not a macro parameter in expansion "
33
34
35
+ case . nonTypeReference( let name) :
36
+ return " reference to type ' \( name) ' that is not a macro type parameter in expansion "
37
+
34
38
case . nonLiteralOrParameter:
35
39
return " only literals and macro parameters are permitted in expansion "
36
40
}
@@ -58,7 +62,14 @@ public enum MacroDefinition {
58
62
/// defining macro. These subtrees will need to be replaced with the text of
59
63
/// the corresponding argument to the macro, which can be accomplished with
60
64
/// `MacroDeclSyntax.expandDefinition`.
61
- case expansion( MacroExpansionExprSyntax , replacements: [ Replacement ] , genericReplacements: [ GenericArgumentReplacement ] ) // FIXME: do we need to evolve this without breaking? I assume so?
65
+ case expansion( MacroExpansionExprSyntax , replacements: [ Replacement ] , genericReplacements: [ GenericArgumentReplacement ] )
66
+ }
67
+
68
+ extension MacroDefinition {
69
+ /// Best effort compatibility shim, the case has gained additional parameters.
70
+ public func expansion( _ node: MacroExpansionExprSyntax , replacements: [ Replacement ] ) -> Self {
71
+ . expansion( node, replacements: replacements, genericReplacements: [ ] )
72
+ }
62
73
}
63
74
64
75
extension MacroDefinition {
@@ -175,27 +186,23 @@ fileprivate class ParameterReplacementVisitor: SyntaxAnyVisitor {
175
186
}
176
187
177
188
override func visit( _ node: GenericArgumentSyntax ) -> SyntaxVisitorContinueKind {
178
- let baseName = " \( node) " // FIXME: where to get the name from properly
189
+ let baseName = node. argument
179
190
guard let genericParameterClause = macro. genericParameterClause else {
180
191
return . skipChildren
181
192
}
182
193
183
194
let matchedParameter = genericParameterClause. parameters. enumerated ( ) . first { ( index, parameter) in
184
- // guard let parameterName = parameter.parameterName else {
185
- // return false
186
- // }
187
-
188
- return true ; // FIXME: what do we need to match here
195
+ return parameter. name. text == " \( baseName) "
189
196
}
190
197
191
198
guard let ( parameterIndex, _) = matchedParameter else {
192
199
// We have a reference to something that isn't a parameter of the macro.
193
- // diagnostics.append(
194
- // Diagnostic(
195
- // node: Syntax(baseName), // FIXME: error should be about type argument
196
- // message: MacroExpanderError.nonParameterReference (baseName)
197
- // )
198
- // )
200
+ diagnostics. append (
201
+ Diagnostic (
202
+ node: Syntax ( baseName) ,
203
+ message: MacroExpanderError . nonTypeReference ( baseName)
204
+ )
205
+ )
199
206
200
207
return . visitChildren
201
208
}
@@ -287,10 +294,14 @@ extension MacroDeclSyntax {
287
294
/// uses of macro parameters with their corresponding arguments.
288
295
private final class MacroExpansionRewriter : SyntaxRewriter {
289
296
let parameterReplacements : [ DeclReferenceExprSyntax : Int ]
297
+ let genericParameterReplacements : [ DeclReferenceExprSyntax : Int ]
290
298
let arguments : [ ExprSyntax ]
291
299
292
- init ( parameterReplacements: [ DeclReferenceExprSyntax : Int ] , arguments: [ ExprSyntax ] ) {
300
+ init ( parameterReplacements: [ DeclReferenceExprSyntax : Int ] ,
301
+ genericReplacements: [ DeclReferenceExprSyntax : Int ] ,
302
+ arguments: [ ExprSyntax ] ) {
293
303
self . parameterReplacements = parameterReplacements
304
+ self . genericParameterReplacements = genericReplacements
294
305
self . arguments = arguments
295
306
super. init ( viewMode: . sourceAccurate)
296
307
}
@@ -311,7 +322,8 @@ extension MacroDeclSyntax {
311
322
private func expand(
312
323
argumentList: LabeledExprListSyntax ? ,
313
324
definition: MacroExpansionExprSyntax ,
314
- replacements: [ MacroDefinition . Replacement ]
325
+ replacements: [ MacroDefinition . Replacement ] ,
326
+ genericReplacements: [ MacroDefinition . GenericArgumentReplacement ]
315
327
) -> ExprSyntax {
316
328
// FIXME: Do real call-argument matching between the argument list and the
317
329
// macro parameter list, porting over from the compiler.
@@ -326,6 +338,11 @@ extension MacroDeclSyntax {
326
338
( replacement. reference, replacement. parameterIndex)
327
339
}
328
340
) ,
341
+ genericReplacements: Dictionary (
342
+ uniqueKeysWithValues: replacements. map { replacement in
343
+ ( replacement. reference, replacement. parameterIndex)
344
+ }
345
+ ) ,
329
346
arguments: arguments
330
347
) . visit ( definition)
331
348
}
@@ -336,12 +353,14 @@ extension MacroDeclSyntax {
336
353
public func expand(
337
354
_ node: some FreestandingMacroExpansionSyntax ,
338
355
definition: MacroExpansionExprSyntax ,
339
- replacements: [ MacroDefinition . Replacement ]
356
+ replacements: [ MacroDefinition . Replacement ] ,
357
+ genericReplacements: [ MacroDefinition . GenericArgumentReplacement ]
340
358
) -> ExprSyntax {
341
359
return expand (
342
360
argumentList: node. arguments,
343
361
definition: definition,
344
- replacements: replacements
362
+ replacements: replacements,
363
+ genericReplacements: genericReplacements
345
364
)
346
365
}
347
366
@@ -351,7 +370,8 @@ extension MacroDeclSyntax {
351
370
public func expand(
352
371
_ node: AttributeSyntax ,
353
372
definition: MacroExpansionExprSyntax ,
354
- replacements: [ MacroDefinition . Replacement ]
373
+ replacements: [ MacroDefinition . Replacement ] ,
374
+ genericReplacements: [ MacroDefinition . GenericArgumentReplacement ]
355
375
) -> ExprSyntax {
356
376
// Dig out the argument list.
357
377
let argumentList : LabeledExprListSyntax ?
@@ -364,7 +384,8 @@ extension MacroDeclSyntax {
364
384
return expand (
365
385
argumentList: argumentList,
366
386
definition: definition,
367
- replacements: replacements
387
+ replacements: replacements,
388
+ genericReplacements: genericReplacements
368
389
)
369
390
}
370
391
}
0 commit comments