I can't generate a class using Kotlin processor









up vote
1
down vote

favorite












I'm implementing a processor to generate kotlin code using custom annotations. The problem is that I cannot find a way to relate the annotation to the field it was declared for, and I cannot find a way to understand if a field is of a nullable type. The processor doesn't succeed to generate the code because the getAnnotationsByType doesn't return the annotations for the current field (the list it's empty). Not even the order is good, fields are passed first and the annotations after all the fields.



package it.kfi.xml.binding.processor

import com.google.auto.service.AutoService
import com.squareup.kotlinpoet.*
import it.kfi.xml.binding.annotations.XmlClass
import it.kfi.xml.binding.annotations.XmlProperty
import java.io.File
import java.lang.reflect.Type
import javax.annotation.Nullable
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.NullType
import javax.lang.model.type.TypeMirror
import javax.print.DocFlavor
import javax.tools.Diagnostic
import kotlin.reflect.KClass
import kotlin.reflect.full.createType



@AutoService(Processor::class)
class XmlBinder : AbstractProcessor()

companion object

const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"


override fun getSupportedAnnotationTypes(): MutableSet<String>

return mutableSetOf(XmlClass::class.java.name)


override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment): Boolean

roundEnv.getElementsAnnotatedWith(XmlClass::class.java)
.forEach
if (it.kind != ElementKind.CLASS)
processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated")
return true

processClass(it)


return false


private fun processClass(element: Element)

val className = element.simpleName.toString() + "Model"
val packageName = processingEnv.elementUtils.getPackageOf(element).toString()

val classBuilder = TypeSpec.classBuilder(className)
classBuilder.addModifiers(KModifier.PUBLIC)

val initFromXml = FunSpec.builder("initFromXml")
initFromXml.addModifiers(KModifier.PUBLIC)
initFromXml.addParameter(ParameterSpec.builder("xml", String::class).build())

val properties = element.enclosedElements

var x: Int = 1

//Look for elements annotated with XmlField and add those elements to the generated class
for (property in properties)

val annotation = property.getAnnotationsByType(XmlProperty::class.java)

val v = 10

classBuilder.addProperty(PropertySpec.varBuilder(property.simpleName.toString(), String::class, KModifier.PUBLIC).initializer(v.toString()).build())
initFromXml.addStatement("this.$property.simpleName = "$v.toString()"")



classBuilder.addFunction(initFromXml.build())

val fileName = "kfi_generated_$className"
val file = FileSpec.builder(packageName, fileName).addType(classBuilder.build()).build()

val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]
file.writeTo(File(kaptKotlinGeneratedDir))






Can anyone help me found a way to relate annotations to their fields or properties ?










share|improve this question























  • Seriously, has nobody a clue on this problem ?
    – Sergiob
    Nov 11 at 9:58










  • How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
    – JEY
    Nov 12 at 8:56











  • I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
    – Sergiob
    Nov 12 at 14:45















up vote
1
down vote

favorite












I'm implementing a processor to generate kotlin code using custom annotations. The problem is that I cannot find a way to relate the annotation to the field it was declared for, and I cannot find a way to understand if a field is of a nullable type. The processor doesn't succeed to generate the code because the getAnnotationsByType doesn't return the annotations for the current field (the list it's empty). Not even the order is good, fields are passed first and the annotations after all the fields.



package it.kfi.xml.binding.processor

import com.google.auto.service.AutoService
import com.squareup.kotlinpoet.*
import it.kfi.xml.binding.annotations.XmlClass
import it.kfi.xml.binding.annotations.XmlProperty
import java.io.File
import java.lang.reflect.Type
import javax.annotation.Nullable
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.NullType
import javax.lang.model.type.TypeMirror
import javax.print.DocFlavor
import javax.tools.Diagnostic
import kotlin.reflect.KClass
import kotlin.reflect.full.createType



@AutoService(Processor::class)
class XmlBinder : AbstractProcessor()

companion object

const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"


override fun getSupportedAnnotationTypes(): MutableSet<String>

return mutableSetOf(XmlClass::class.java.name)


override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment): Boolean

roundEnv.getElementsAnnotatedWith(XmlClass::class.java)
.forEach
if (it.kind != ElementKind.CLASS)
processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated")
return true

processClass(it)


return false


private fun processClass(element: Element)

val className = element.simpleName.toString() + "Model"
val packageName = processingEnv.elementUtils.getPackageOf(element).toString()

val classBuilder = TypeSpec.classBuilder(className)
classBuilder.addModifiers(KModifier.PUBLIC)

val initFromXml = FunSpec.builder("initFromXml")
initFromXml.addModifiers(KModifier.PUBLIC)
initFromXml.addParameter(ParameterSpec.builder("xml", String::class).build())

val properties = element.enclosedElements

var x: Int = 1

//Look for elements annotated with XmlField and add those elements to the generated class
for (property in properties)

val annotation = property.getAnnotationsByType(XmlProperty::class.java)

val v = 10

classBuilder.addProperty(PropertySpec.varBuilder(property.simpleName.toString(), String::class, KModifier.PUBLIC).initializer(v.toString()).build())
initFromXml.addStatement("this.$property.simpleName = "$v.toString()"")



classBuilder.addFunction(initFromXml.build())

val fileName = "kfi_generated_$className"
val file = FileSpec.builder(packageName, fileName).addType(classBuilder.build()).build()

val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]
file.writeTo(File(kaptKotlinGeneratedDir))






Can anyone help me found a way to relate annotations to their fields or properties ?










share|improve this question























  • Seriously, has nobody a clue on this problem ?
    – Sergiob
    Nov 11 at 9:58










  • How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
    – JEY
    Nov 12 at 8:56











  • I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
    – Sergiob
    Nov 12 at 14:45













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I'm implementing a processor to generate kotlin code using custom annotations. The problem is that I cannot find a way to relate the annotation to the field it was declared for, and I cannot find a way to understand if a field is of a nullable type. The processor doesn't succeed to generate the code because the getAnnotationsByType doesn't return the annotations for the current field (the list it's empty). Not even the order is good, fields are passed first and the annotations after all the fields.



package it.kfi.xml.binding.processor

import com.google.auto.service.AutoService
import com.squareup.kotlinpoet.*
import it.kfi.xml.binding.annotations.XmlClass
import it.kfi.xml.binding.annotations.XmlProperty
import java.io.File
import java.lang.reflect.Type
import javax.annotation.Nullable
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.NullType
import javax.lang.model.type.TypeMirror
import javax.print.DocFlavor
import javax.tools.Diagnostic
import kotlin.reflect.KClass
import kotlin.reflect.full.createType



@AutoService(Processor::class)
class XmlBinder : AbstractProcessor()

companion object

const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"


override fun getSupportedAnnotationTypes(): MutableSet<String>

return mutableSetOf(XmlClass::class.java.name)


override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment): Boolean

roundEnv.getElementsAnnotatedWith(XmlClass::class.java)
.forEach
if (it.kind != ElementKind.CLASS)
processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated")
return true

processClass(it)


return false


private fun processClass(element: Element)

val className = element.simpleName.toString() + "Model"
val packageName = processingEnv.elementUtils.getPackageOf(element).toString()

val classBuilder = TypeSpec.classBuilder(className)
classBuilder.addModifiers(KModifier.PUBLIC)

val initFromXml = FunSpec.builder("initFromXml")
initFromXml.addModifiers(KModifier.PUBLIC)
initFromXml.addParameter(ParameterSpec.builder("xml", String::class).build())

val properties = element.enclosedElements

var x: Int = 1

//Look for elements annotated with XmlField and add those elements to the generated class
for (property in properties)

val annotation = property.getAnnotationsByType(XmlProperty::class.java)

val v = 10

classBuilder.addProperty(PropertySpec.varBuilder(property.simpleName.toString(), String::class, KModifier.PUBLIC).initializer(v.toString()).build())
initFromXml.addStatement("this.$property.simpleName = "$v.toString()"")



classBuilder.addFunction(initFromXml.build())

val fileName = "kfi_generated_$className"
val file = FileSpec.builder(packageName, fileName).addType(classBuilder.build()).build()

val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]
file.writeTo(File(kaptKotlinGeneratedDir))






Can anyone help me found a way to relate annotations to their fields or properties ?










share|improve this question















I'm implementing a processor to generate kotlin code using custom annotations. The problem is that I cannot find a way to relate the annotation to the field it was declared for, and I cannot find a way to understand if a field is of a nullable type. The processor doesn't succeed to generate the code because the getAnnotationsByType doesn't return the annotations for the current field (the list it's empty). Not even the order is good, fields are passed first and the annotations after all the fields.



package it.kfi.xml.binding.processor

import com.google.auto.service.AutoService
import com.squareup.kotlinpoet.*
import it.kfi.xml.binding.annotations.XmlClass
import it.kfi.xml.binding.annotations.XmlProperty
import java.io.File
import java.lang.reflect.Type
import javax.annotation.Nullable
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.NullType
import javax.lang.model.type.TypeMirror
import javax.print.DocFlavor
import javax.tools.Diagnostic
import kotlin.reflect.KClass
import kotlin.reflect.full.createType



@AutoService(Processor::class)
class XmlBinder : AbstractProcessor()

companion object

const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"


override fun getSupportedAnnotationTypes(): MutableSet<String>

return mutableSetOf(XmlClass::class.java.name)


override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment): Boolean

roundEnv.getElementsAnnotatedWith(XmlClass::class.java)
.forEach
if (it.kind != ElementKind.CLASS)
processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated")
return true

processClass(it)


return false


private fun processClass(element: Element)

val className = element.simpleName.toString() + "Model"
val packageName = processingEnv.elementUtils.getPackageOf(element).toString()

val classBuilder = TypeSpec.classBuilder(className)
classBuilder.addModifiers(KModifier.PUBLIC)

val initFromXml = FunSpec.builder("initFromXml")
initFromXml.addModifiers(KModifier.PUBLIC)
initFromXml.addParameter(ParameterSpec.builder("xml", String::class).build())

val properties = element.enclosedElements

var x: Int = 1

//Look for elements annotated with XmlField and add those elements to the generated class
for (property in properties)

val annotation = property.getAnnotationsByType(XmlProperty::class.java)

val v = 10

classBuilder.addProperty(PropertySpec.varBuilder(property.simpleName.toString(), String::class, KModifier.PUBLIC).initializer(v.toString()).build())
initFromXml.addStatement("this.$property.simpleName = "$v.toString()"")



classBuilder.addFunction(initFromXml.build())

val fileName = "kfi_generated_$className"
val file = FileSpec.builder(packageName, fileName).addType(classBuilder.build()).build()

val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME]
file.writeTo(File(kaptKotlinGeneratedDir))






Can anyone help me found a way to relate annotations to their fields or properties ?







kotlin






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 at 8:28









Jayson Minard

35.1k13103170




35.1k13103170










asked Nov 9 at 18:01









Sergiob

203412




203412











  • Seriously, has nobody a clue on this problem ?
    – Sergiob
    Nov 11 at 9:58










  • How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
    – JEY
    Nov 12 at 8:56











  • I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
    – Sergiob
    Nov 12 at 14:45

















  • Seriously, has nobody a clue on this problem ?
    – Sergiob
    Nov 11 at 9:58










  • How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
    – JEY
    Nov 12 at 8:56











  • I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
    – Sergiob
    Nov 12 at 14:45
















Seriously, has nobody a clue on this problem ?
– Sergiob
Nov 11 at 9:58




Seriously, has nobody a clue on this problem ?
– Sergiob
Nov 11 at 9:58












How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
– JEY
Nov 12 at 8:56





How do you compile the code ? In gradle you might need a specific configuration docs.gradle.org/current/userguide/…
– JEY
Nov 12 at 8:56













I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
– Sergiob
Nov 12 at 14:45





I created a Java-Library (not Android-library... it doesn't work) for the annotation classes and one Java-Library for the processor, as explained also here:medium.com/@Miqubel/…
– Sergiob
Nov 12 at 14:45


















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53231101%2fi-cant-generate-a-class-using-kotlin-processor%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53231101%2fi-cant-generate-a-class-using-kotlin-processor%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Use pre created SQLite database for Android project in kotlin

Darth Vader #20

Ondo