Let's look at the following case where I want to use macros to extend an enum type as follows:
Source:
enum MyEnum {
case intValue(Int)
case stringValue(string: String)
}
Destination:
enum MyEnum {
case intValue(Int)
case stringValue(string: String)
enum CaseLabel {
case intValue, stringValue
}
var caseLabel: CaseLabel {
switch self {
case .intValue:
.intValue
case .stringValue:
.stringValue
}
}
}
extension MyEnum: CaseLabeled {}
While CaseLabeled
is a public protocol
public protocol CaseLabeled {
associatedtype CaseLabel: Equatable
var caseLabel: CaseLabel { get }
}
I have implemented this with a member
and an extension
macro.
If MyEnum
is public, the CaseLabel
and caseLabel
declarations must also be public due to the public protocol conformance:
public enum MyEnum {
case intValue(Int)
case stringValue(string: String)
public enum CaseLabel {
case intValue, stringValue
}
public var caseLabel: CaseLabel {
switch self {
case .intValue:
.intValue
case .stringValue:
.stringValue
}
}
}
What I can do in the MemberMacro
implementation is to retrieve the modifiers of the enum to find out if CaseLabel
and caseLabel
need to be made public.
So sth. like
// 'declaration' is an EnumDeclSyntax
let isPublicEnum = declaration.modifiers.contains { modifier in
modifier.name.text == "public"
}
But this only works if the developer doesn't put the enum declaration into a public extension like this:
public extension SomeType {
@CaseLabeled
enum MyEnum {
case intValue(Int)
case stringValue(string: String)
}
}
This results in MyEnum
also being public
. But in this case I do not have a corresponding modifier in the macro code at the node, as it is present on the enclosing element.
As a result, CaseLabel
and caseLabel
on the expanded enum do not have the correct access level.
So the question is:
How do I get the effective access level of the type to be extended by the macro?
It doesn't seem like you can get information about the parent node hierarchy in a macro.
Of course, you can ask the developers to make sure that they always define the access level at the enum itself when using the macro, but that doesn't seem like a good solution to me.