Skip to content

Commit c2e0139

Browse files
committed
macros: prepare generic arguments for replacement in macros
1 parent 2664baa commit c2e0139

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

Sources/SwiftSyntaxMacroExpansion/MacroReplacement.swift

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public enum MacroDefinition {
5858
/// defining macro. These subtrees will need to be replaced with the text of
5959
/// the corresponding argument to the macro, which can be accomplished with
6060
/// `MacroDeclSyntax.expandDefinition`.
61-
case expansion(MacroExpansionExprSyntax, replacements: [Replacement])
61+
case expansion(MacroExpansionExprSyntax, replacements: [Replacement], genericReplacements: [GenericArgumentReplacement]) // FIXME: do we need to evolve this without breaking? I assume so?
6262
}
6363

6464
extension MacroDefinition {
@@ -70,11 +70,21 @@ extension MacroDefinition {
7070
/// The index of the parameter in the defining macro.
7171
public let parameterIndex: Int
7272
}
73+
74+
/// A replacement that occurs as part of an expanded macro definition.
75+
public struct GenericArgumentReplacement {
76+
/// A reference to a parameter as it occurs in the macro expansion expression.
77+
public let reference: GenericArgumentSyntax
78+
79+
/// The index of the parameter in the defining macro.
80+
public let parameterIndex: Int
81+
}
7382
}
7483

7584
fileprivate class ParameterReplacementVisitor: SyntaxAnyVisitor {
7685
let macro: MacroDeclSyntax
7786
var replacements: [MacroDefinition.Replacement] = []
87+
var genericReplacements: [MacroDefinition.GenericArgumentReplacement] = []
7888
var diagnostics: [Diagnostic] = []
7989

8090
init(macro: MacroDeclSyntax) {
@@ -156,6 +166,45 @@ fileprivate class ParameterReplacementVisitor: SyntaxAnyVisitor {
156166
return .visitChildren
157167
}
158168

169+
override func visit(_ node: GenericArgumentClauseSyntax) -> SyntaxVisitorContinueKind {
170+
return .visitChildren
171+
}
172+
173+
override func visit(_ node: GenericArgumentListSyntax) -> SyntaxVisitorContinueKind {
174+
return .visitChildren
175+
}
176+
177+
override func visit(_ node: GenericArgumentSyntax) -> SyntaxVisitorContinueKind {
178+
let baseName = "\(node)" // FIXME: where to get the name from properly
179+
guard let genericParameterClause = macro.genericParameterClause else {
180+
return .skipChildren
181+
}
182+
183+
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
189+
}
190+
191+
guard let (parameterIndex, _) = matchedParameter else {
192+
// 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+
// )
199+
200+
return .visitChildren
201+
}
202+
203+
genericReplacements.append(.init(reference: node, parameterIndex: parameterIndex))
204+
205+
return .visitChildren
206+
}
207+
159208
override func visitAny(_ node: Syntax) -> SyntaxVisitorContinueKind {
160209
if let expr = node.as(ExprSyntax.self) {
161210
// We have an expression that is not one of the allowed forms, so
@@ -230,7 +279,7 @@ extension MacroDeclSyntax {
230279
throw DiagnosticsError(diagnostics: visitor.diagnostics)
231280
}
232281

233-
return .expansion(definition, replacements: visitor.replacements)
282+
return .expansion(definition, replacements: visitor.replacements, genericReplacements: visitor.genericReplacements)
234283
}
235284
}
236285

0 commit comments

Comments
 (0)