I'm trying to write my first macro, and I am baffled trying to figure out how to actually see what the arguments are. I've written this type signature in one module:
@freestanding(declaration)
public macro example(_ arg: KeyValuePairs<String, Int>) = // ...
Then, in another module, I've added this struct:
public struct ExampleMacro: MemberMacro {
public static func expansion(
of node: SwiftSyntax.AttributeSyntax,
providingMembersOf declaration: some SwiftSyntax.DeclGroupSyntax,
in context: some SwiftSyntaxMacros.MacroExpansionContext
) throws -> [SwiftSyntax.DeclSyntax] {
// There's no way you have to do this just to get your macro arguments. That's way too convoluted.
guard case .argumentList(let args) = node.arguments,
let firstArg = args.first else {
fatalError()
}
let firstArgExpr = firstArg.expression
// ...okay, so I have an ExprSyntax. How do I get the KVP<String,Int> out of it?
}
}
You can see some of my frustration in the comments in the code above. All the examples I can find in official documentation say to use node.argumentList.first?.expression, but that gives me the error "value of type 'AttributeSyntax' has no member 'argumentList'". But I understand that different macros receive different kinds of nodes and so I might just be looking at the wrong one.
Still, this question from above remains:
so I have an ExprSyntax. How do I get the KVP<String,Int> out of it?
I can't even figure out what I can do with an ExprSyntax. Autocomplete is less than helpful:
What I want to make would take the keys as the property names and use the values to provide information about the properties. For the sake of simplicity (though this isn't exactly my end goal) let's say that what I want to do is this:
After scrolling through the whole list in the autocomplete menu, the only thing I can think of is to convert it back to a string and parse out the dictionary literal myself. There’s no way that’s what I have to do, I just know it, but the documentation is sparse.
Thanks, this has been helpful! Now I'm stuck on getting the value out of a IntegerLiteralExprSyntax. Int(iles.trimmedDescription) works for a basic decimal literal like 16, but not 0x10 or 1_6. Is there a designated utility to get the value out of a literal?
I’ve made a library called SwiftMacroToolkit which can do exactly that! It can get the values of literals (supporting every format that swift does including hex), and help get arguments from a macro succinctly, among many other useful features which make macros much easier to write. It’s currently still experimental but in my opinion it’s already pretty useful.