Overview
I'm wondering if there's a way I can apply annotations to functions and access the body of those functions during annotation processing. If it's not possible to directly get the method body through inspection of Element objects within the annotation processor, are there any other alternatives to accessing the source code of the function that these annotations are applied to?
Details
As part of a project I'm working on, I'm trying to use kapt to inspect Kotlin functions annotated with a specific type of annotation and generate classes based on them. For example, given an annotated function like this:
@ElementaryNode
fun addTwoNumbers(x: Int, y: Int) = x + y
My annotation processor currently generates this:
class AddTwoNumbers : Node {
val x: InputPort<Int> = TODO("implement node port property")
val y: InputPort<Int> = TODO("implement node port property")
val output: OutputPort<Int> = TODO("implement node port property")
}
However, I need to include the original function itself in this class, essentially just as if it were copy/pasted in as a private function:
class AddTwoNumbers : Node {
val x: InputPort<Int> = TODO("implement node port property")
val y: InputPort<Int> = TODO("implement node port property")
val output: OutputPort<Int> = TODO("implement node port property")
private fun body(x: Int, y: Int) = x + y
}
What I've tried
Based on this answer, I tried using com.sun.source.util.Trees to access the method body of the ExecutableElement corresponding to the annotated functions:
override fun inspectElement(element: Element) {
if (element !is ExecutableElement) {
processingEnv.messager.printMessage(
Diagnostic.Kind.ERROR,
"Cannot generate elementary node from non-executable element"
)
return
}
val docComment = processingEnv.elementUtils.getDocComment(element)
val trees = Trees.instance(processingEnv)
val body = trees.getTree(element).body
processingEnv.messager.printMessage(Diagnostic.Kind.WARNING, "Processing ${element.simpleName}: $body")
}
However, kapt only generates stubs of method bodies, so all I got for each method body was stuff like this:
$ gradle clean build
...
> Task :kaptGenerateStubsKotlin
w: warning: Processing addTwoNumbers: {
return 0;
}
w: warning: Processing subtractTwoNumbers: {
return 0.0;
}
w: warning: Processing transform: {
return null;
}
w: warning: Processing minAndMax: {
return null;
}
w: warning: Processing dummy: {
}
Update
Accessing Element.enclosingElement on the ExecutableElement representing each function gives me the qualified name of the package/module where the function is defined. For example, addTwoNumbers is declared as a top-level function in Main.kt, and during annotation processing I get this output: Processing addTwoNumbers: com.mycompany.testmaster.playground.MainKt.
Is there a way I can access the original source file (Main.kt) given this information?
