Adding protocol conformance to a new declaration

I'm a little lost on something, perhaps someone can point me in the right direction.

I've created a new DeclarationMacro that constructs a new type say, "struct Foo".

A great example where this seems to have been achieved is in the new #Preview macro which both generates a new type, and adds its own Preview conformance too.

Basically I want this same behaviour.

Regardless any advice here would be appreciated :+1:

Hey there,

So, in the world of Swift, there's this thing called the inheritanceClause property inside StructDeclSyntax. I believe it could pretty good fit for your case. It's basically adding conforms to some protocol in your new declaration.

Here's a little Swift code to show you what I mean. Let's say you've got a struct Foo and you want it to play nice with a protocol Fooable:

public static func expansion(
    of node: some FreestandingMacroExpansionSyntax,
    in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
    [
        DeclSyntax(
            StructDeclSyntax(
                identifier: .identifier("Foo"),
                inheritanceClause: TypeInheritanceClauseSyntax {
                    InheritedTypeSyntax(
                        typeName: SimpleTypeIdentifierSyntax(
                            name: .identifier("Fooable")
                        )
                    )
                },
                memberBlockBuilder: {
                    // Members...
                }
            )
        )
    ]
}

If you're into the details and want to dive deeper, you might find the docs on StructDeclSyntax and inheritanceClause useful.

I hope this helps! Just shoot me a reply if anything's not clear or you have more questions.

2 Likes

Hey, thank you for this! Unfortunately it leads me to the same error I had with my own approaches:

Use of protocol 'PreviewProvider' as a type must be written 'any PreviewProvider'

I tried both PreviewProvider and SwiftUI.PreviewProvider in case it was a namespacing issue.

I have an interesting update. I re-tested by simply copy-pasting your code and THAT WORKS!

The error I showed you earlier occurred when I tried with PreviewProvider from SwiftUI.

Why is that different?

Any chance @bnbarham or @Douglas_Gregor could chime in here, could this be a bug?

For additional reference, you can see here the expansion "looks" fine. I've removed the use of makeUniqueName for brevity here.

Here's the code from the macro.

This is a proof of concept and more about learning Macro's, so there's some hard-coded values like "ContentView" which I know to exist ofc.
Also, note this isn't trying to backport much more than the syntactic sugar and convenience that #Preview provides since much of the implementation I think is baked into Xcode :+1:

@Ian_Keen came across this issue a few days ago. You can find his message here: Unwanted spaces in StringLiteral output - #4 by Ian_Keen

1 Like

The any diagnostics in macro expansions were a compiler bug that is fixed by [5.9] [Macros] Fix existential diagnostics for declaration macro expansions by rxwei · Pull Request #66152 · apple/swift · GitHub. You can test out the fix in recent Swift 5.9 development snapshots from Swift.org - Download Swift

4 Likes