Unwanted spaces in StringLiteral output

I'm attempting to build a fairly simple macro:

public struct PreviewWithBindingsMacro: ExpressionMacro {
    public static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) -> ExprSyntax {
        guard let builder = node.trailingClosure?.trimmed else {
            fatalError("trailing closure expected")
        }

        let prefix = context.createUniqueName("View")

        let previews = try! StructDeclSyntax("struct \(raw: prefix)_Previews: PreviewProvider") {
            try VariableDeclSyntax("static var previews: some View") {
              StmtSyntax("PreviewView \(raw: builder)")
            }
        }

        return "\(raw: previews.formatted())"
    }
}

I wonder if im holding this right.. there are a couple of problems
Firstly, The test input is

#PreviewWithBindings { bindings in
    Text("Hello")
}

and the output is:

struct __macro_local_4ViewfMu__Previews: PreviewProvider {
    static var previews: some View {
        PreviewView { bindings in
            Text("  Hello")
        }
    }
}

Note the additional spaces in the text String literal. Am I constructing the struct and outputting correctly?

Secondly, literal issue aside no matter what I do xcode will not recognize my preview and open the preview pane.. is there something hardcoded into xcode to only look for blessed macros? copy/pasting my macro output allows the pane to appear but xcode must not look at it otherwise?

The problem is that you declared PreviewWithBindingsMacro as an ExpressionMacro, but the macro is generating a declaration. This probably throws the parser off in multiple ways and makes it generate a completely invalid tree. Change the macro to a DeclarationMacro and you should be fine. That way you can also return previews as DecSyntax(previews), without the need for another string interpolation.

Good point on using the wrong type! but after updating the issue persists :frowning_face:

There's also a possible bug, the compiler is saying:

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

Even though copy/pasting the expanded code works without issue.

There's a feedback at FB12326868 for anyone able to peek into it.

Can you share the macro package with a test case that reproduces the issue? I suspect there’s some other issue where a node is parsed as a different type than it should be.

1 Like

Yup, no problem.

@freestanding(declaration, names: arbitrary)
public macro MyMacro<Content: View>(@ViewBuilder _ content: () -> Content) -> Void = #externalMacro(module: "MyMacros", type: "MyMacro")
public struct MyMacro: DeclarationMacro {
    public static func expansion<Node: FreestandingMacroExpansionSyntax, Context: MacroExpansionContext>(
        of node: Node,
        in context: Context
    ) throws -> [DeclSyntax] {
        guard let builder = node.trailingClosure?.trimmed else { fatalError("trailing closure expected") }

        let prefix = context.createUniqueName("View")

        let previews = try StructDeclSyntax("struct \(raw: prefix)_Previews: PreviewProvider") {
            try VariableDeclSyntax("static var previews: some View") {
              StmtSyntax("Wrapper \(raw: builder)")
            }
        }

        return [DeclSyntax(previews)]
    }
}```

```swift
assertMacroExpansion(
    """
    #MyMacro {
        Text("Hello")
    }
    """,
    expandedSource: """
    struct __macro_local_4ViewfMu__Previews: PreviewProvider {
        static var previews: some View {
            Wrapper {
                Text("Hello")
            }
        }
    }
    """,
    macros: ["MyMacro": MyMacro.self]
)

the diff provided with the test failure is:

 struct __macro_local_4ViewfMu__Previews: PreviewProvider {
     static var previews: some View {
         Wrapper {
–            Text("Hello")
+            Text(" Hello")
         }
     }
 }

The call to wrapper is a function call expression and so it needs to be

ExprSyntax("Wrapper \(raw: builder)")

ah that worked. thanks!

I dont suppose you might know if its possible to make xcode recognize my code and open the preview pane (which I can't even do manually)

actually nevermind.. I forgot im blocked on the compiler bug :+1: