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

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.

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.

2 Likes

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. : )