Invalid types in kotlin annotation handler

I am working on an annotation processor for Kotlin, and since the processed elements are in Java, I am not getting nullables how ? instead with the @Nullable annotation @Nullable and this is fine, but I have a problem with getting null parameters in types and in higher order functions, for normal parameters.

 var someNullField: String? = "" 

I get java.lang.String in the process with @org.jetbrains.annotations.Nullable in my annotations.

But List<String?> , For example, will return me java.util.List<java.lang.String> without any annotations, not in the main element, but not in type arguments that lead to an unknown state of uncertainty

I tried using javax.lang.model.util.Types to find some kind of result but nothing.

Some of the code I'm using now:

 val utils = processingEnvironment.typeUtils val type = fieldElement.asType() if (type is DeclaredType) { val typeElement = utils.asElement(type) type.typeArguments .forEach { //Trying different ways and just printing for possible results val capture = utils.capture(it) val erasure = utils.erasure(it) val element = utils.asElement(it) printMessage("element: $element isNullable: ${element.isNullable()} isNotNull: ${element.isNotNull()}\ncapture: $capture isNullable: ${capture.isNullable()} isNotNull: ${capture.isNotNull()}\nerasure: $erasure isNullable: ${erasure.isNullable()} isNotNull: ${erasure.isNotNull()}") } } 

All help would be appreciated.

+7
java annotations kotlin annotation-processing kapt
source share
1 answer

A bit of a necessary story: with Java 6 (when the Mirror API was released) Java annotations could not be used on anything, but on the same top-level elements accessible through reflection. You could annotate classes, methods, and fields, but you could not annotate type arguments ( List<String> ) or local variables ( String value = ... ). Sun / Oracle engineers confirmed this limitation, and so-called "type annotations" appeared in Java 8.

Type annotations can be targeted at the type of something: the type of the local variable, the type of the component of the array, the type of the type of the variable, and even the type of return (the subsequent annotation is placed similarly, but differs from the old school annotations on the method!). Type annotations are created using the new @Target : ElementType # TYPE_USE value .

When people of Kotlin write

 List<String?> 

It really means

 List<@Nullable String> 

which can be read as: "list of Stable String elements".

Since the type itself is targeted, you expect to get annotations by looking at its original TypeMirror (don't worry about erased or captured TypeMirrors, they don’t have enough connection to the source code to save annotations). By the way, the Mirror API was reorganized, as a result, a new interface appeared AnnotatedConstruct and it is convenient to make TypeMirror its descendant.


Now the bad news: by the time Java 8 was released, support for checking type annotations was apparently not ready for production, so it was running. JSR has been rewritten to mean that "TypeMirror # getAnnotationMirrors" should return nothing.

Support bits that have been removed from the public API are still available through the Oracle-specific Tree API provider (only supported in javac). The Mirror type returned by Tree # getTypeMirror may contain the annotation as you expect. But since this is a mistake, you can only get annotations through a series of hacks, and ultimately it won’t work all the time (for example, in the case of nested type arguments). See this question for some research in this direction.

The fix for this mess was combined in Java 9. I have not tested it yet, but it looks like TypeMirror # getAnnotationMirrors may finally work. Planning for backup fixes for the old version of Java is not planned.

+3
source share

All Articles