Annotation Processor: printing a message (and doing it in a new line)
This is a really simple and direct tutorial, but it really took me more than I want to admit to understand why this wasn’t working as expected, and since there isn’t much information about it I thought it’s worth sharing — annotation processor: printing a message (and doing it in a new line).
Printing a message
Printing a message in the build console is quite simple, you just need to call ProcessingEnvironment.Message.printMessage(Kind, CharSequence).
In order to access this method, you need to extend the class AbstractProcessor and override the process function, something like:
class GenerateProcessor : AbstractProcessor() {
override fun process(p0: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Hello")
return true
}
}
And if you look at the build view, you can see the “Hello” message printed:
**Note: **you need to switch to the build view on your Android Studio.
If you look at printMessage arguments you can see that it receives one that corresponds to Kind and the other to the message that you want to print. This first argument can be one of the following types:
- ERROR
When there’s a problem that requires that the compilation ends. - WARNING
There’s a problem that requires attention but it’s not severe to the point that the compilation needs to end. - MANDATORY_WARNING
A problem similar to a warning, but it’s from the specification itself. - NOTE
An informative message. - OTHER
When the message to be printed doesn’t belong in any of the above criteria.
If you switch the Kind value to ERROR when printMessage is executed the compilation will end.
Printing a message in a new line
The above example works fine but what if you want to add multiple calls to printMessage?
override fun process(p0: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Hello")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "This is one message")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "This is another message")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "And yet another")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Well you got the point")
return true
}
Well, it’s not particularly easy to read them:
On this simple example, you’ve removed the other tasks that are printed while you compile the project — but trust me, on a large project these debug lines get pretty difficult to read.
The solution is not the same that you’re used to. You can’t just fix it by adding a new line — \n, since it‘s ignored by the system. Alternatively, you’ll need to add \r\n if you want to have messages on multiple lines:
override fun process(p0: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Hello\r\n")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "This is one message\r\n")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "This is another message\r\n")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "And yet another\r\n")
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Well you got the point\r\n")
return true
}
Note: \r
corresponds to the carriage return
Special thanks to Burkhard Mittelbach who pointed me on the right answer.
Conclusion
Debugging an annotation processor is always a bit tricky — and since you’re dealing with code that is generated in compile the entire process can cause some headaches.
Now that you’ve seen how you could use printMessage in order to add build logs, let me also share an article that I’ve written a while back on how to debug annotation processor in Kotlin: Debug annotation processor in Kotlin
Do you have a better approach? Something didn’t quite work with you? Feel free to send me a message 🙂.