In Swift Macros, how can I remove extra indentation from CodeBlockItemListSyntax?
06:18 21 Dec 2025

I am writing a method that runs a closure and measure how long it took the code to run. In the output, I want to include the actual source code that is run, so the method takes two parameters like this:

func measure(_ block: () -> T, _ blockDescription: StaticString) -> T {
    let start = Date()
    let result = block()
    let duration = Date().timeIntervalSince(start)
    print( // I'm outputting to some markdown file, but for simplicity's sake let's just use 'print'
        """
        ```swift
        \(blockDescription)
        ```
        
        took \(duration) seconds.
        """
    )
    return result
}

The intended usage is like this:

measure({ 
    doSomething() 
    doSomethingElse() 
}, """
doSomething()
doSomethingElse()
""")

Of course, manually repeating the statements in the closure is not maintainable at all, so I tried to write a freestanding expression macro to do this. The macro will find the closure, and convert that to a StringLiteralExprSyntax. As a result, I only need to do

#measure {
    doSomething() 
    doSomethingElse()
}

Here is my implementation:

enum MeasureMacro: ExpressionMacro {
    static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) throws -> ExprSyntax {
        let closure = if let firstArg = node.arguments.first?.expression.as(ClosureExprSyntax.self) {
            firstArg
        } else if let trailingCLosure = node.trailingClosure {
            trailingCLosure
        } else {
            throw MacroExpansionErrorMessage("Missing closure")
        }
        let closureString = closure.statements.trimmedDescription
        let argList = LabeledExprListSyntax {
            LabeledExprSyntax(expression: closure)
            LabeledExprSyntax(expression: StringLiteralExprSyntax(content: closureString))
        }
        return "measure(\(argList))"
    }
}

I thought using trimmedDescription would remove all the extra indentation, but it only does it for the first line. It ends up generating the string literal:

"doSomething()\n    doSomethingElse()"

whereas I wanted

"doSomething()\ndoSomethingElse()"

I tried adding .formatted() before trimmedDescription, but that does not change anything.

How can I remove the indentation?

swift swift-macro swift-syntax