3

I'm following Hello World of Annotation Processing in Kotlin and KotlinPoet's documentation and am trying to implement a generic builder for Kotlin. I'd like to generically create a method for every field in an annotated data class and give it's argument the same name and type of the field. The problem is that I cannot find which type the field has, given the instance of javax.lang.model.element.Element that I have. Here's what I managed that far:

fieldsIn(klass.enclosedElements)
            .forEach {
                classBuilder
                        .addProperty(PropertySpec
                                .builder(it.toString(), String::class, KModifier.INTERNAL)
                                .mutable(true)
                                .initializer("\"\"")
                                .build())

                classBuilder
                        .addFunction(FunSpec
                                .builder(it.toString())
                                .addParameter(ParameterSpec
                                        .builder(
                                                it.toString(), 
                                                it.?) // what to use here?
                                        .build())
                                .build())
            }

How can I find the type of the field? I read in the documentation that you should use method asType() but this return an instance of TypeMirror. I can't really see how to continue from here. Any suggestions are welcome.

uzilan
  • 2,554
  • 2
  • 31
  • 46

2 Answers2

3

I ended up using this function:

private fun getClass(it: VariableElement): KClass<*> {
    val type = it.asType()

    return when (type.kind) {
        TypeKind.DECLARED -> Class.forName(type.toString()).kotlin
        TypeKind.BOOLEAN -> Boolean::class
        TypeKind.BYTE -> Byte::class
        TypeKind.SHORT -> Short::class
        TypeKind.INT -> Int::class
        TypeKind.LONG -> Long::class
        TypeKind.CHAR -> Char::class
        TypeKind.FLOAT -> Float::class
        TypeKind.DOUBLE -> Double::class
        else -> throw Exception("Unknown type: $type, kind: ${type.kind}")
    }
}
uzilan
  • 2,554
  • 2
  • 31
  • 46
0
.addMember("%N", "${it.asType()}::class")
Murdokai
  • 173
  • 1
  • 10
  • you need to add some explanation. Posting the code only might not be helpful – Mr. Alien Mar 05 '19 at 02:49
  • The problem is to get cKlass from type, which is possible to do as described in authors answer, but Class.forName() will work only if your processor module is aware about the cKlass you're trying to create. In my situation it is not the case, but a workaround with setting name "%N" instead of type "%T" and just adding a "::class" string - worked. – Murdokai Mar 05 '19 at 07:02