Kotlin Compiler Plugin to check annotation on catch block exception variable?


#1

What I want to do is this:

try { } catch (@AutoLog e: Exception) { //generate a log statement here }

i.e. when the exception variable in catch block is annotated with @AutoLog, generate a log statement automatically in the beginning of catch block during build process.

I tried to do that by creating my own Kotlin compiler plugin. But I just found:

  1. ‘backend’ extensions works on jvm byte code and jvm byte code does not retain annotations on exception variable (and more generally, all local variables). I watched Kevin Most’s Kotlin Compiler plugin talk at Kotlin Conf 2018, and checked the Kotlin source code(in the path compiler/backend/src/org/jetbrains/kotlin/codegen/extensions). ‘backend’ plugins can add log statement but seem not able to check the existence of @AutoLog on Exception variable.

  2. ‘frontend’ extensions should do the job, but there is no example to show how to do similar things. The existing extensions in the path compiler/frontend/src/org/jetbrains/kotlin/extensions are all coarse-grained, e.g. DeclarationAttributeAltererExtension , don’t show how to manipulate the AST(Abstract syntax tree), which I suppose I have to work on to achieve my goal.

So, my question is , do I have to use Compiler plugin, particularly frontend entensions to do that, and how? Thanks.


#2

The answer is yes. You cannot do this with annotation processing (it cannot change existing code). The backend is for generating platform specific code from the AST. The front-end is about creating the AST (and manipulating it). The API is unfortunately neither document, very straightforward, nor supported yet.

For your particular problem, why not create a LoggableException that does logging internally rather than relying on your developers not forgetting to add an annotation. Instead for a general loop that catches generic Exception objects, use a fun <R> logExceptions(body: ()->R):R function that does the logging (then rethrows for specific handling) but does not hide it inside a compiler plugin.


#3

Thank you for the reply. I can do try {} catch (e: Exception) { log(e); }, with a customized log function. That is not that much code, but I do want to cut the non-functional code to the minimum, while meantime maintain the normal syntax, that’s why I want the @AutoLog thing. Still want to be able to achieve that with compiler plugin. : )