kotlinannotationsannotation-processing

Annotation processor is not processing annotations in kotlin


I had written a couple annotation processors in the past, mainly for processing classes annotated with certain annotations and creating an object to easily manipulate those classes or perform certain actions on them. My issue is, I'm currently writing an annotation processor that would work on functions, not classes, and in my super simple test project the processor is not picking up on the function that is annotated with my annotation, and I can't figure out why. The annotation processor is simple in my sample, but I'll omit the code generator, since it's not even getting to that point. My annotation processor...

//NavigationDestination.kt
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
annotation class NavigationDestination()

//Processor.kt
class Processor: AbstractProcessor() {
  override fun getSupportedAnnotationTypes() = mutableSetOf(NavigationDestination::class.java.canonicalName)

  override fun process(p0: MutableSet<out TypeElement>?, p1: RoundEnvironment): Boolean {
    println("Starting the processor")
    val annotatedElements = p1.getElementsAnnotatedWith(NavigationDestination::class.java)
    val types = mutableListOf<TypeElement>().apply {
      addAll(ElementFilter.typesIn(annotatedElement))
    }
    println("How many elements are there? ${types.size}")
    val itemsToProcess = mutableListOf<TypeElement>()
    types.forEach { type -> 
      if(isValidFunction(type)) {
        itemsToProcess.add(type)
      }
    }
    println("itemsToProcess.size: ${itemsToProcess.size}")
    if(itemsToProcess.isNotEmpty()) {
      //build the code here... never makes it to this
    }
    return true
  }

  private fun isValidFunction(elem: TypeElement): Bolean {
    if(elem.kind != ElementKind.METHOD) {
      processingEnv.messager.printMessage(Diagnostic.Kind.Error, "Only functions allowed")
      return false
    }    
    return true
}

Then in my sample project I add the annotation to my project and add it as a kapt processor in my build.gradle file, and created a super simple test, just to see if it's grabbing the annotations...

//MainActivity.kt
class MainActivity: ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContent {
      NavTestTheme {
        Scaffold(modifier = Modifier.fillMaxSize()) {
          Greeting(name = "Rob", modifier = Modifier.padding(it))
        }
      }
    }
  }
}
@Composable
fun greeting(name: String, modifier: Modifier = Modifier) {
  Text("hello $name", modifier = modifier)
}

@NavigationDestination
fun addGreeting() {
    Log.d("MAINACTIVITY", "JUST TESTING:")
}

So now everything should be set, I enable kapt verbose and showProcessorStats in my build.gradle file and build the project and in the build window I get...

Starting the processor How many elements are there? 0 itemsToProcess.size: 0


Solution

  • You are filtering for TypeElement instead of ExecutableElement.

    If you replace this

    val types = mutableListOf<TypeElement>().apply {
        addAll(ElementFilter.typesIn(annotatedElement))
    }
    

    with this

    val methods = mutableListOf<ExecutableElement>().apply {
        addAll(ElementFilter.methodsIn(annotatedElement))
    }
    

    it will work.