Weird prefix spaces added when processing my macro

Hi,

I've been playing around with macros and I found myself in a situation where I got attached accessor macro with 2 parameters - url and method. Both are strings.

It looks like this

public struct MyMacroMacro: AccessorMacro {
    public static func expansion<Context, Declaration>(
        of node: AttributeSyntax,
        providingAccessorsOf declaration: Declaration,
        in context: Context
    ) throws -> [AccessorDeclSyntax] where Context : MacroExpansionContext, Declaration : DeclSyntaxProtocol {
        guard let expressions = node.argument?.as(TupleExprElementListSyntax.self) else {
            //TODO throw error
            return []
        }
        
        let segments = expressions.compactMap { $0.expression.as(StringLiteralExprSyntax.self)?.segments }
        let params = segments.compactMap { $0.trimmedDescription }
        
        guard params.count == 2 else {
            //TODO throw error
            return []
        }
        
        return [
            """
            .init(url: url + "\(raw: params[0])", method: "\(raw: params[1])")
            """
        ]
    }
}

Now, when I call it like:

struct MyStruct {
let url = "https://apple.com"
@MyMacro(url: "/test", method: "some") var myVar: MyCustomType

it produces something like this:

struct MyStruct {
let url = "https://apple.com"
var myVar: MyCustomType
{
    .init(url: url + " /test", method: " some")
}

I have no idea why it adds those whitespaces. When debugging, before calling "return" there are no whitespaces in "/test" or "some".

Also - is there a way to create a macro that'll call another macro? For example MySecondMacro(url: "/url") to call MyMacro(url: "/url", method: "second")?

  • One more thing - I tried with hardcoded values like """ .init(url: url + "/test", method: "get") """ and it still added those whitespaces

Add a Comment

Accepted Reply

Issue solved. I was missing get keyword. The return statement of AccessorMacro should look like this:

return [
    """
    get {
        .init(url: url + "\(raw: params[0])", method: "\(raw: params[1])")
    """
]

Replies

PS: It's worth mentioning I tried to do it with (literal:) instead of (raw:) too but the result was the same

Issue solved. I was missing get keyword. The return statement of AccessorMacro should look like this:

return [
    """
    get {
        .init(url: url + "\(raw: params[0])", method: "\(raw: params[1])")
    """
]