title: Using TreeTranslator to rename functions not working for Kotlin
body: <p>I am trying to rename a method in a Java interface and a function in a Kotlin interface during building according to AST (Abstract Syntax Tree) rewriting. For this question we ignore the implications that renaming a method/function brings for invocations. To find the method/function to rename I am using a custom annotation and annotation processor. I have it working for the Java interface by following these instructions.</p>
  
  <p>I created a new project with three modules. The app module, annotation module and annotation processor module.</p>
  
  <p>The app module is an Android App and contains two separate Java and Kotlin interface files with one annotated method/function each.</p>
  
  <p><strong>RenameJava.java</strong></p>
  
  <pre><code>package nl.peperzaken.renametest;
  
  import nl.peperzaken.renameannotation.Rename;
  
  public interface RenameJava {
      @Rename
      void methodToRename();
  }
  </code></pre>
  
  <p><strong>RenameKotlin.kt</strong></p>
  
  <pre><code>package nl.peperzaken.renametest
  
  import nl.peperzaken.renameannotation.Rename
  
  interface RenameKotlin {
      @Rename
      fun functionToRename()
  }
  </code></pre>
  
  <p>The annotation module is a Java Library that only contains the <code>@Rename</code> annotation and we specify to only allow it on functions and we say it may only be visible in the source code.</p>
  
  <p><strong>Rename.kt</strong></p>
  
  <pre><code>package nl.peperzaken.renameannotation
  
  @Target(AnnotationTarget.FUNCTION)
  @Retention(AnnotationRetention.SOURCE)
  annotation class Rename
  </code></pre>
  
  <p>The annotation processor module is a Java Library that only contains the processor that iterates the elements that have the annotation and do transformations on them.</p>
  
  <p><strong>RenameProcessor.kt</strong></p>
  
  <pre><code>package nl.peperzaken.renameprocessor
  
  import com.google.auto.service.AutoService
  import com.sun.source.util.Trees
  import com.sun.tools.javac.processing.JavacProcessingEnvironment
  import com.sun.tools.javac.tree.JCTree
  import com.sun.tools.javac.tree.TreeTranslator
  import com.sun.tools.javac.util.Names
  import nl.peperzaken.renameannotation.Rename
  import javax.annotation.processing.*
  import javax.lang.model.SourceVersion
  import javax.lang.model.element.TypeElement
  import javax.tools.Diagnostic
  
  @AutoService(Processor::class)
  @SupportedSourceVersion(SourceVersion.RELEASE_8)
  @SupportedAnnotationTypes("nl.peperzaken.renameannotation.Rename")
  class RenameProcessor : AbstractProcessor() {
  
      private lateinit var trees: Trees
      private lateinit var names: Names
  
      private val visitor = object : TreeTranslator() {
          override fun visitMethodDef(jcMethodDecl: JCTree.JCMethodDecl) {
              super.visitMethodDef(jcMethodDecl)
  
              // print original declaration
              processingEnv.messager.printMessage(
                  Diagnostic.Kind.NOTE,
                  jcMethodDecl.toString()
              )
  
              // Rename declaration
              jcMethodDecl.name = names.fromString("renamed")
  
              // print renamed declaration
              processingEnv.messager.printMessage(
                  Diagnostic.Kind.NOTE,
                  jcMethodDecl.toString()
              )
  
              // commit changes
              result = jcMethodDecl
          }
      }
  
      @Synchronized
      override fun init(processingEnvironment: ProcessingEnvironment) {
          super.init(processingEnvironment)
          trees = Trees.instance(processingEnvironment)
          val context = (processingEnvironment as JavacProcessingEnvironment).context
          names = Names.instance(context)
      }
  
      override fun process(set: Set&lt;TypeElement&gt;, roundEnvironment: RoundEnvironment): Boolean {
          // Find elements that are annotated with @Rename
          for (element in roundEnvironment.getElementsAnnotatedWith(Rename::class.java)) {
              val tree = trees.getTree(element) as JCTree
              tree.accept(visitor)
          }
          return true
      }
  }
  </code></pre>
  
  <p><strong>Gradle files</strong></p>
  
  <p>I added the following to the annotation processor <code>build.gradle</code>:</p>
  
  <pre><code>// Add annotation dependency
  implementation project(':rename-annotation')
  // Used to generate META-INF so the processor can run
  compile 'com.google.auto.service:auto-service:1.0-rc4'
  kapt "com.google.auto.service:auto-service:1.0-rc4"
  // To prevent unresolved references during building. You might not need this dependency.
  implementation files("${System.getProperty('java.home')}/../lib/tools.jar")
  </code></pre>
  
  <p>I added the following to the app <code>build.gradle</code>:</p>
  
  <pre><code>compileOnly project(':rename-annotation')
  annotationProcessor project(':rename-processor')
  </code></pre>
  
  <p>The annotation <code>build.gradle</code> doesn't have dependencies besides the default generated ones.</p>
  
  <p>The reason we have different modules is so we can prevent the annotation and processor being build into the final APK since we only need those during building.</p>
  
  <p><strong>Output</strong></p>
  
  <p>The log shows the method in the Java interface was renamed:</p>
  
  <pre><code>Note: 
    @Rename()
    void methodToRename();
  Note: 
    @Rename()
    void renamed();
  </code></pre>
  
  <p>There was no log generated for the Kotlin interface. Indicating the annotation processor did not run.</p>
  
  <p>When you take a look at <code>classes.dex</code> of the generated APK then you will see the following:</p>
  
  <p><a href="https://i.stack.imgur.com/Z10b6.png" rel="noreferrer"><img src="https://i.stack.imgur.com/Z10b6.png" alt="Output annotationProcessor"></a></p>
  
  <p>You can see that the method of the Java interface has been renamed properly. While the function of the Kotlin interface has not. Even though it shows up in the log.</p>
  
  <p>You will also notice this warning in the log:</p>
  
  <blockquote>
    <p>app: 'annotationProcessor' dependencies won't be recognized as kapt annotation processors. Please change the configuration name to 'kapt' for these artifacts: 'RenameTest:rename-processor:unspecified' and apply the kapt plugin: "apply plugin: 'kotlin-kapt'".</p>
  </blockquote>
  
  <p>So lets do what the warning suggests. Add <code>apply plugin: 'kotlin-kapt'</code> to app <code>build.gradle</code> and change <code>annotationProcessor</code> to <code>kapt</code>. After sync and rebuild the output is:</p>
  
  <pre><code>Note: 
    @Rename()
    void methodToRename();
  Note: 
    @Rename()
    void renamed();
  Note: 
    @nl.peperzaken.renameannotation.Rename()
    public abstract void functionToRename();
  Note: 
    @nl.peperzaken.renameannotation.Rename()
    public abstract void renamed();
  </code></pre>
  
  <p>Logs for the Java and Kotlin file are both appearing. Success you think? Looking at <code>classes.dex</code> of the newly generated APK will make you think otherwise since both are in their original form:</p>
  
  <p><a href="https://i.stack.imgur.com/DEG1C.png" rel="noreferrer"><img src="https://i.stack.imgur.com/DEG1C.png" alt="Output kapt"></a></p>
  
  <p><strong>Question</strong></p>
  
  <p>Is there a way to get the desired output in the final APK? With the output being that both the method in the Java interface and the function in the Kotlin interface are renamed.</p>
  
  <p>Link to sample project: <a href="https://github.com/peperzaken/kotlin-annotation-rename-test" rel="noreferrer">https://github.com/peperzaken/kotlin-annotation-rename-test</a></p>