Freestanding function declaration macro

Hi,

I'm working on a freestanding macro that should create a function definition. For example

@MacroExample("funcA")

// Expands to:
func MacroFunc_funcA() { }

I've declared the macro like this:

@freestanding(declaration)
public macro MacroExample(_ key: String) = #externalMacro(
    module: "MyMacros",
    type: "MacroExample"
)

and implemented it like this (hardcoded the result for simplicity in this example):

public struct MacroExample: DeclarationMacro {
  public static func expansion(
    of node: some SwiftSyntax.FreestandingMacroExpansionSyntax,
    in context: some SwiftSyntaxMacros.MacroExpansionContext)
    throws -> [SwiftSyntax.DeclSyntax] {
      return [
        "func MacroFunc_funcA() { }"
      ]
  }
}

However, I get the complier error "Declaration name 'MacroFunc_funcA' is not covered by macro 'MacroExample'". This works if I add "names: named(MacroFunc_funcA)" however I want the name of the function to be based on the string the user provides to the macro. It does not work when I use names: prefixed(MacroFunc_).

If I make a macro that generates a type declaration I can use any name I want, why is this not working for a function declaration/is there a way to get it to work?

Thanks!

Hmm… I guess my first question might be if you were able to confirm that the ability to create a type declaration from a freestanding macro without explicitly specifying the names argument is actually intended and supported.

I have seen situations before where macros that I would think should require names actually seem to not require names:

I have been able to make it work with a type definition both without names and with names: prefixed(...) but neither of these worked for functions. So even if it wouldn't work without names, I thought at least the prefixed version would work.

I was trying to do a similar thing, specifically a macro which makes a top level function with a name supplied as a String Literal.

This is disappointing. It seems like Swift Macros could be astonishingly powerful, but every time I try and use them, I run into a limit with no workaround, save just using gyb.

I suppose the problem might be the String possibly having an interpolation, which makes me wonder if Swift needs a Final String Literal, so no interpolation.

1 Like

Wouldn't that be StaticString?

1 Like

Ohhh, yes!

And that gets me back to the same not covered thing OP was talking about. Oh well.

The expansion is so close, though.