I want to create a macro which copies cases from one enum to another. I would imagine something like this:
enum ChildEnum {
case childA
case childB
}
@CaseProxy(ChildEnum.self)
enum ParentEnum {
case parent
}
which will generate:
enum ParentEnum {
case parent
///Generated
case childA
case childB
}
I tried to create the macro, but I don't know how to use node: AttributeSyntax to get to the members of the given type that I pass as an argument.
With this design, you cannot. Macros are not full-fledged source generators. They operate on the AST, not the semantics of the code. As far as the macro is concerned,
ChildEnum.selfis just the wordChildEnum, a period, and the wordself. It cannot know what casesChildEnumhas, unless you pass all the cases' names into the macro.And if you do pass all the cases into
@CaseProxy, that kind of defeats the purpose of having a macro. You might as well just write them inside the enum declaration normally.An alternative design would be to have an additional declaration macro take in a
() -> Voidclosure. Inside the closure, you can declare enums:Now both enums are "inputs" to
#ProxyableEnums, and so#ProxyableEnumscan read the contents of the closure, and see what cases each enum has. Then, it can find enums that are annotated with@CaseProxy. Using this information,#ProxyableEnumswill expand to one or more enum declarations - for every enum without@CaseProxy, it will expand to that same enum declaration, and for every enum with@CaseProxy, it will expand to an enum declaration with the added cases. Notably,@CaseProxydoesn't expand to anything - it's just a "marker" for#ProxyableEnums.The obvious limitation here is that the child and parent enums must be in the same file.
Here is a very simple implementation: