Despite reviewing some other discussions and (solved) bug reports concerning this problem (topic, issue, issue, topic) I am still not successful at relocating error messages to the right position, the column is still wrong. The goal of my code is to use the body of the function as a closure to an added function call, the code
@Step func step1(during execution: Execution) {
print("hello")
}
becomes
func step1(during execution: Execution) {
execution.effectuate(checking: StepID(crossModuleFileDesignation: #file, functionSignature: #function)) {
print("hello")
}
}
Displayed message are displayed in the right line, but the column is too far to the right, because an indentation is added during the expansion (despite the formatMode setting).
My macro implementation (repo):
extension SyntaxStringInterpolation {
mutating func appendInterpolation<Node: SyntaxProtocol>(
_ node: Node,
location: AbstractSourceLocation?,
lineOffset: Int? = nil,
close: Bool = true
) {
if let location {
let line = if let lineOffset {
ExprSyntax("\(literal: Int(location.line.as(IntegerLiteralExprSyntax.self)?.literal.text ?? "0")! + lineOffset)")
} else {
location.line
}
var block = CodeBlockItemListSyntax {
"#sourceLocation(file: \(location.file), line: \(line))"
"\(node)"
}
if close {
block.append("\n#sourceLocation()")
}
appendInterpolation(block)
} else {
appendInterpolation(node)
}
}
}
public struct StepMacro: BodyMacro {
public static var formatMode: FormatMode { .disabled }
public static func expansion(
of node: AttributeSyntax,
providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
in context: some MacroExpansionContext
) throws -> [CodeBlockItemSyntax] {
return [
"""
execution.effectuate("doing something in step1", checking: StepID(crossModuleFileDesignation: #file, functionSignature: #function)) {
\(declaration.body!.statements, location: context.location(of: declaration.body!.statements, at: .beforeLeadingTrivia, filePathMode: .filePath), lineOffset: 1)
}
"""
]
}
}
Notes:
- I find it quite useful to just add the textual additions to the code, not having to compose those statements in some complex manner.
- The above insertion of the old body between the new parentheses does not use any indentation by itself, to not make the false localization of the error message even worse, but of course the following would be nice when looking at the expansion (with an indentation added):
...
return [
"""
execution.effectuate("doing something in step1", checking: StepID(crossModuleFileDesignation: #file, functionSignature: #function)) {
\(declaration.body!.statements, location: context.location(of: declaration.body!.statements, at: .beforeLeadingTrivia, filePathMode: .filePath), lineOffset: 1)
}
"""
]
...
Thank you for your help!