How to use Kotlin Symbol Processing (KSP) to populate an existing list

1.8k views Asked by At

I've been playing recently with KSP and have managed to develop interesting capabilities (such as automatic recyclerview and view holder generators based on their layout id), and so far all is well.

However, I am now trying to do something different than creating files based on the annotations I design. Instead of creating files, I would only want to populate a list with the classes/objects annotated by me.

Example:

ClassA.kt

@MyAnnotation
class ClassA(context: Context): SomeBaseClass(context) {
    override fun baseClassFunction() {
        // custom code goes here
    }
}

ClassB.kt

@MyAnnotation
class ClassB(context: Context): SomeBaseClass(context) {
    override fun baseClassFunction() {
        // custom code goes here
    }
}

MyListAgregator.kt

object MyListAgregator {
    const val classList: List<SomeBaseClass> = mutableListOf()
}

Where my custom KSP would do the following

  1. Collect all classes/objects (the usual) that are annotated by my @MyAnnotation
  2. Create an instance of them with the appropriate parameters (in this case just a context)
  3. Add each one to the classList in the MyListAgregator

I can always get to the point of the class collection (step 1) but the rest is a complete mystery to me, and feels like KSP always expects to create code, not execute it? Perhaps I am incorrect on the later one, but I could not find anything related to that explained in the available documentation.

Another alternative I considered, but would rather avoid out of concern for any negative hit (performance, for example) is to actually modify that MyListAgregator file directly to include all the instances in the list, as if I had written them myself. However, I would still prefer to go with the previous option instead if it is at all possible.

1

There are 1 answers

0
Nikola Despotoski On

First, you need to establish a ruleset that will be applied to the classes annotated with your annotation (symbol in KSP glossary). For example, they must contain one argument, that argument must be a member property and of type Context and must be subclass of SomeBaseClass. I suggest first look up for correct inheritance then look up for argument count and type.

You are still within reading and exploring all files with this symbol. Filtering based on this ruleset you will land with a set of classes at point 2.

Here, KSP can provide you with the interface to generate your code. However, KSP will not let you edit the source file, but generate new one based on your conditions. Here you have to write your implementation for the overriden function, by visiting it

You can preserve the output (newly generated classes at step 2) and generate your MyListAggregator object.