There’s an open question in the implementation that we need to resolve that may have public API impacts, see below: Body macros on properties - #2 by cal
I also wonder if we should support body macros on properties without a body in the original source. This is supported for functions:
static func expansion(
of node: AttributeSyntax,
providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
in context: some MacroExpansionContext
) throws -> [CodeBlockItemSyntax]
This works for get / set accessors (AccessorDeclSyntax, conforms to WithOptionalCodeBlockSyntax) but doesn’t work out of the box for properties without explicit accessors (VariableDeclSyntax doesn’t conform to WithOptionalCodeBlockSyntax).
Should we introduce a new expansion signature for computed properties without accessors?
static func expansion(
of node: AttributeSyntax,
providingBodyFor declaration: VariableDeclSyntax, // new
in context: some MacroExpansionContext
) throws -> [CodeBlockItemSyntax]
Or, should we make this work through the existing WithOptionalCodeBlockSyntax signature (implementation options discussion here)?
If we prefer a new signature, this seems like it would need to be ran as an amendment to SE-0415. Would love a suggestion from the LSG on the direction here.
Right, I was about to say something about using accessor macros here.
I think what might be annoying about this in practice, though, is that I don't believe you can overload a macro solely based on its role. For example, if you wanted to be able to provide the same interface for generated functions and read-only properties:
@Generated func f()
@Generated var x: Int
and have @Generated generate a body for f and a getter for x, it's not possible to declare macro Generated with the same signature but only differing by @attached(body) vs. @attached(accessor). You'd have to rename one, which is unfortunate.
Or, you just have to write this instead:
@Generated func f()
var x: Int { @Generated get }
But from your initial post it sounds like that isn't supported yet.
I see, yeah that’s an unfortunate consequence. Confirmed in a sample project that this doesn’t work. However, it seems perfectly reasonable to have a single body macro that supports being applied to both functions and properties.
I don’t really see a reason why body macros definitely shouldn’t support providing a getter body for a property without a body in the original source. It seems logical and feels like it composes well with the other capabilities of body macros.
Are there any downsides to supporting this in body macros? If not, maybe we can add the capability?
If you can already add a body macro to:
@MyBodyMacro
var x: Int {
1
}
It seems almost confusingly inconsistent that you can’t apply it to:
@MyBodyMacro
var x: Int
Given this exact syntactical transformation (append a curly brace block to the existing partial declaration) is available for body macros on func declarations.