Experimenting with annotation processors - is ther...
# kapt
s
Experimenting with annotation processors - is there an easy in way to figure out whether an annotated property is nullable? The mirror APIs don’t have any information on this. I looked a bit into kotlinx metadata library, but I must be using it in a wrong way as all the flags I’m getting back are nullable … (the flag absolute value is 551). Here’s the code I’m using to gather the flags:
Copy code
val metadataAnnotation = typeElement.getAnnotation(Metadata::class.java)
        val header = KotlinClassHeader(
            metadataAnnotation.kind,
            metadataAnnotation.metadataVersion,
            metadataAnnotation.bytecodeVersion,
            metadataAnnotation.data1,
            metadataAnnotation.data2,
            metadataAnnotation.extraString,
            metadataAnnotation.packageName,
            metadataAnnotation.extraInt
        )

        val metadata = KotlinClassMetadata.read(header)
        when (metadata) {
            is KotlinClassMetadata.Class -> {
                metadata.accept(object: KmClassVisitor()  {
                    override fun visitProperty(
                        flags: Flags,
                        name: String,
                        getterFlags: Flags,
                        setterFlags: Flags
                    ): KmPropertyVisitor? {
                        val nullable = Flag.Type.IS_NULLABLE(flags)
                        Logger.logW("* visiting property $name, flags: $flags, nullable: $nullable")
                        return super.visitProperty(flags, name, getterFlags, setterFlags)
                    }
                })
            }
            else -> {
                Logger.logW("bummer ... not a class: $metadata")
            }
        }
Anyone can see anything?
Also tried to read the metadata annotation at runtime using reflection, but I’m getting the same results. Looks like there is something wrong with the generated metadata in my classes …
s
You can check if that property has another annotation with `Nullable`/`NonNull`/`NotNull`. Usually Kotlin non-nulls have the
NotNull
annotation
s
Right - that is one possible way, but I was hoping to use the metadata as it can give me additional valuable information
g
Metdata is the only correct way, not reading nullable annotations
s
That's true. Reading nullable annotations is useful when your annotation processor runs on mixed sources.
g
if it’s on mixed sources it should check is this class has kotlin metadata (it’s Kotlin type) or not (it’s Java)
s
What's a nice way to do that? Any code that you can point me to?
g
not really, you can just check for Kotlin metadata annotation
m
s
Nice! Will check it out
t
IIRC inside your
visitProperty
you need to return a
KmPropertyVisitor
and
visitReturnType
. The nullability will be in the
Flags
there
Some code I have that does this, looks like this:
Copy code
override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor? {
        return MetadataPropertyVisitor(
            onBuild = { properties.put(it.name, it) },
            name = name,
            outerFlags = flags
        )
Copy code
internal class MetadataPropertyVisitor(
    private val onBuild: (DeclaredProperty) -> Unit,
    private val name: String,
    private val outerFlags: Flags
): KmPropertyVisitor() {
    override fun visitReturnType(flags: Flags): KmTypeVisitor? {
        val property = DeclaredProperty(
            name = name,
            isNullable = Flag.Type.IS_NULLABLE(flags),
            isPrivate = Flag.IS_PRIVATE(outerFlags)
        )
        onBuild(property)
        return super.visitReturnType(flags)
    }
}
(It’s a library that does what I suspect @Marc Knaup has written, but before that existed
m
The visitor pattern was way too much boilerplate for me and too complicated, so I wrote a wrapper around it which basically reutbds plenty of easily navigable data glasses.
t
@Marc Knaup I did the same but never got around to open sourcing it. When I saw you did one I made a note to check it out and see if I can dump mine
😮 1
s
Thanks @tddmonkey, this is exactly what I needed. How did you figure this one out? The documentation is not exactly explaining this one ….
t
Failing tests, the debugger and a lot of patience 😄
Once you get very familiar with the AST it’s not too bad
s
Nice. Thanks for taking the one for the team 🙂
😀 1