You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Swift宏实现枚举案例跨枚举复制?AttributeSyntax使用疑问

Swift宏实现枚举案例代理的解决方案

核心逻辑

要实现@CaseProxy(ChildEnum.self)这种枚举案例复制的宏,核心是两步:从属性注解里解析出目标枚举类型,再通过Swift的语义分析能力拿到该枚举的所有案例,最后把这些案例代码插入到父枚举中。

具体实现步骤

1. 从AttributeSyntax提取目标枚举类型

先写个工具函数,把@CaseProxy(ChildEnum.self)里的ChildEnum类型提取出来:

func extractTargetEnum(from attribute: AttributeSyntax) -> TypeSyntax? {
    guard let args = attribute.arguments?.as(LabeledExprListSyntax.self),
          let firstArg = args.first?.expression.as(MemberAccessExprSyntax.self),
          let enumName = firstArg.base.as(IdentifierExprSyntax.self)?.identifier.text,
          firstArg.name.text == "self" else {
        return nil
    }
    return TypeSyntax("\(raw: enumName)")
}

2. 通过语义模型获取枚举的案例成员

在宏的扩展方法里,利用SemanticModel查询目标枚举的完整声明,进而提取所有案例:

func expand(
    attribute: AttributeSyntax,
    providingMembersOf declaration: some DeclGroupSyntax,
    in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
    // 拿到目标枚举的类型语法
    guard let targetType = extractTargetEnum(from: attribute),
          // 解析类型对应的符号
          let typeSymbol = context.semanticModel.resolveType(targetType)?.symbol,
          // 转成枚举声明节点
          let enumDecl = typeSymbol.declaration.as(EnumDeclSyntax.self) else {
        throw MacroError.failedToResolveEnum
    }
    
    // 遍历枚举成员,筛选出所有案例
    let caseElements = enumDecl.memberBlock.members
        .compactMap { $0.decl.as(EnumCaseDeclSyntax.self) }
        .flatMap { $0.elements }
    
    // 生成父枚举需要的case声明
    return caseElements.map { element in
        DeclSyntax("case \(element.name)")
    }
}

3. 定义宏和错误类型

先声明自定义错误类型:

enum MacroError: Error {
    case failedToResolveEnum
}

再定义宏的公开接口:

@freestanding(declaration, names: arbitrary)
public macro CaseProxy(_ enumType: Any.Type) = #externalMacro(module: "YourMacroModule", type: "CaseProxyMacro")

记得把YourMacroModule替换成你的宏所在的模块名称。

使用示例

enum ChildEnum {
    case childA
    case childB
}

@CaseProxy(ChildEnum.self)
enum ParentEnum {
    // 宏会自动生成以下代码:
    // case childA
    // case childB
}

内容的提问来源于stack exchange,提问作者JaSHin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 10:54:57