Accessing a protocol's functions with SwiftSyntax

I'm attempting to generate default implementations for a protocol using a macro. The goal is something like this:

protocol Foo {
    var one: String { get }
    func two()
}

@GenerateDefaultImplementations
extension Foo {} // add generated defaults for `var one: String` and `func two()`.

I have GenerateDefaultImplementations set up as a MemberMacro however I'm struggling to figure out how I can access the members of Foo from the macro that is on the extension.

struct GenerateDefaultImplementations: MemberMacro {
    static func expansion(
        of node: AttributeSyntax,
        providingMembersOf declaration: some DeclGroupSyntax,
        in context: some MacroExpansionContext
    ) throws -> [DeclSyntax] {
        guard let ext = declaration.as(ExtensionDeclSyntax.self) else {
            return []
        }

        guard let extendedType = ext.extendedType.as(SimpleTypeIdentifierSyntax.self) else {
            return []
        }

        // âť“ How can I access the functions of `extendedType` (in this case `Foo`) here?
    }
}

Is it possible to access the functions of Foo in a macro on this extension, even though it was defined elsewhere? If so, how can I do that?

1 Like

Would you be able to achieve this more easily by instead creating a peer macro that you can attach to the protocol itself? As far as I can tell, peer macros should be able to produce extension declarations, but I haven't tried it for myself

Yes that would be the ideal situation, unfortunately macros currently aren’t allowed to create extensions :confused:. I’m exploring if there’s a passable workaround.

1 Like

A similar question, if I pass a Type to a macro, there is no way to that macro to get information about it right?

@DoSomething(AnotherUnrelatedProtocol.self)
struct A {}

The macro has info about A but it can't get info about AnotherUnrelatedProtocol correct?

Yeah, sadly it seems that macros don't get any context other than the syntax they're attached to (if any) and the syntax of their arguments. It makes sense in terms of keeping things simple, but I can definitely see something like you described being being pitched in future. It seems like it would be a good way of passing wider context hygienically to macros.

2 Likes

It probably won’t be allowed in the future due to performance issues with that. If they are, I’m sure it would be source file constrained.