I am trying to emit error messages from my Swift macro.
I saw that every kind of macro's expansion
function has a MacroExpansionContext
parameter, and it has a diagnose
method, so presumably that is the intended way to emit errors.
diagnose
takes a Diagnostic
, so I tried to create an instance of that. I saw that its initialiser takes a syntax node and a DiagnosticMessage
. The syntax node I can easily pass, but DiagnosticMessage
is a protocol. Using Xcode's fix-its, I managed to write such a type that conforms to DiagnosticMessage
,
struct MyMessage: DiagnosticMessage {
let message: String
var diagnosticID: MessageID {
.init(domain: "some domain", id: "some id")
}
var severity: DiagnosticSeverity {
.error
}
}
And passing this worked as expected,
context.diagnose(Diagnostic(
node: declaration, message: MyMessage(message: "You must attach this macro to a class!")
))
But surely I am not supposed to write something like this every time I write a macro, right? Is there some type in SwiftSyntax that conforms to DiagnosticMessage
that I can directly use?
I have tried searching in the documentation for SwiftSyntax on Swift Package Index and found nothing there. Interestingly, I couldn't even find DiagnosticMessage
there.
MacroExpansionErrorMessage
is a built-in type that conforms to DiagnosticMessage
, so you can just write:
context.diagnose(Diagnostic(
node: declaration, message: MacroExpansionErrorMessage("You must attach this macro to a class!")
))
There is also MacroExpansionWarningMessage
for warnings.
These are in the SwiftSyntaxMacros module, which is why you couldn't find it on the linked page, which only shows the documentation for the SwiftSyntax module.