2

I'm fiddling around with the new Swift 5.9 Macros.

I have the following macro:

Given the following enum

@associatedValues
enum Fruit {
    case banana(Banana)
    case grape(Grape)
}

I want

@associatedValues
enum Fruit {
    case banana(Banana)
    case grape(Grape)

    var bananaValue: Banana? { if ... return ... } }
    var grapeValue: Grape? { if ... return ... } }
}

My implementation is like so:

public static func expansion<Declaration, Context>(
        of node: SwiftSyntax.AttributeSyntax,
        providingMembersOf declaration: Declaration,
        in context: Context
    ) throws -> [SwiftSyntax.DeclSyntax]
    where Declaration: SwiftSyntax.DeclGroupSyntax,
          Context: SwiftSyntaxMacros.MacroExpansionContext
    {
        
        guard let enumDeclaration = declaration.as(EnumDeclSyntax.self) else {
            throw AssociatedValuesMacroError.onlyApplicableToEnum
        }
        
        return enumDeclaration.memberBlock.members
            .compactMap { $0.decl.as(EnumCaseDeclSyntax.self) }
            .map { (_case: EnumCaseDeclSyntax) in

                let _element: EnumCaseElementListSyntax.Element = _case.elements.first!
                let caseName = _element.identifier
                let typeName = _element.associatedValue!.parameterList.first!.description

                return
                    """
                    var \(raw: caseName)Value: \(raw: typeName)? {
                        if case let .\(raw: caseName)(value) = self {
                            return value
                        } else {
                            return nil
                        }
                    }
                    """
            }
    }

Now, the autocompletion detects the new properties, but the compiler tells me:

Declaration name 'bananaValue' is not covered by macro 'associatedValues'

Declaration name 'grapeValue' is not covered by macro 'associatedValues'

The tests run and validate the output but not when compiling.

enter image description here

enter image description here

What am I missing? Thank you

Nuno Gonçalves
  • 6,202
  • 7
  • 46
  • 66
  • I got the same issue, but trying to return a function. Have you found out why this is? – Vollan Jun 09 '23 at 09:16
  • I advanced by adding “names: arbitrary” to the attachment declaration. But then I hit another issue which I haven’t solved yet so I didn’t write an answer yet. – Nuno Gonçalves Jun 09 '23 at 13:09
  • I think this is needed to tell the compiler they any name is possible. – Nuno Gonçalves Jun 09 '23 at 13:11
  • Most ***is*** provided as text, but not all. See *[Why not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/questions/285551/)* (e.g., *"Images should only be used to illustrate problems that* ***can't be made clear in any other way,*** *such as to provide screenshots of a user interface."*) – Peter Mortensen Jun 12 '23 at 14:44
  • @PeterMortensen the images display Xcode behaviour showing an autocomplete and an error. In this case IMHO I think it's ok to use them. – Nuno Gonçalves Jun 13 '23 at 22:27

1 Answers1

10

We need to add names: arbitrary to the macro role.

@attached(member, names: arbitrary)
public macro AssociatedValues() = #externalMacro(module: "MyMacrosModule", type: "AssociatedValuesMacro")

Note: In my case I needed arbitrary because the names are dynamic. But if you do know what attributes you're adding, you should use names: myCustomName instead.


Also, though not an answer to the specific question, but make sure you add your macro type to the list of providing Macros in CompilerPlugin.

#if canImport(SwiftCompilerPlugin)
import SwiftCompilerPlugin
import SwiftSyntaxMacros

@main
struct MacrosPlugin: CompilerPlugin {
  let providingMacros: [Macro.Type] = [
      AssociatedValueMacro.self
  ]
}
Nuno Gonçalves
  • 6,202
  • 7
  • 46
  • 66