Daniel Amarante
Daniel Amarante

Reputation: 805

How to generate an enum with associated values using swift macros?

When trying to generate an enum with associated values, the generated enum is missing comma separating it's values.

This is the my expansion function (I'm using a PeermMacro)

public enum MyMacro: PeerMacro {

    public static func expansion(
        of _: AttributeSyntax,
        providingPeersOf _: some DeclSyntaxProtocol,
        in _: some MacroExpansionContext
    ) throws -> [DeclSyntax] {
        [
            DeclSyntax(
                EnumDeclSyntax(name: "MyEnum") {
                    EnumCaseDeclSyntax {
                        EnumCaseElementSyntax(
                            name: "myCase",
                            parameterClause: EnumCaseParameterClauseSyntax(
                                parameters: EnumCaseParameterListSyntax(
                                    [
                                        EnumCaseParameterSyntax(type: TypeSyntax("Int")),
                                        EnumCaseParameterSyntax(type: TypeSyntax("String"))
                                    ]
                                )
                            )
                        )
                    }
                }
            )
        ]
    }
}

The code above generates the following code, which doesn't compile because there's a comma missing between the associated values:

enum MyEnum {
    case myCase(Int String)
}

How can I update my expansion code so that the generated code contains comma between my associated values?

Upvotes: 1

Views: 253

Answers (1)

Sweeper
Sweeper

Reputation: 271380

In the same way that you passed a result builder closure to EnumDeclSyntax and EnumCaseDeclSyntax, you can do that to EnumCaseParameterListSyntax too.

EnumCaseParameterListSyntax {
    EnumCaseParameterSyntax(type: TypeSyntax("Int")),
    EnumCaseParameterSyntax(type: TypeSyntax("String"))
)

Many of the AST nodes conform to ExpressibleByStringInterpolation, so you can further simplify this to

EnumCaseParameterListSyntax {
    "Int"
    "String"
)

In fact, given a list of enum case parameters, you can generate the whole enum declaration using an interpolated string literal:

static func enumDeclWithParameters(_ list: [EnumCaseParameterSyntax]) -> DeclSyntax {
    let parameterList = EnumCaseParameterListSyntax {
        for elem in list {
            elem
        }
    }
    return """
    enum MyEnum {
        case myCase(\(parameterList)
    }
    """
}

Upvotes: 3

Related Questions