Annotating Java API with @NotNull to be "Kotlin Friendly" (preferably at type level rather than method level)


#1

Hi, I have Java API that I want to make “Kotlin Friendly”.

I was hoping to just annotate the relatively few methods that return null with @Nullable. This mostly works apart from the issue that when I use auto-complete in IDEA the return type defaults to a nullable type (which I then have to manually change to a non-nullable type).

To make my Java API “Kotlin Friendly” with the correct non-nullable type provided correctly by IDE auto-complete it seems I need to annotation those methods with @NotNull. This is 99% of my methods.

Ideally I could have a class level @NotNull annotation (target ElementType.TYPE) that indicates that all the methods on this class return non-null types EXCEPT for the ones that are explicitly annotated with @Nullable (and there are only 1 or 2 of those so this would be good).

Does anyone have something like this?

Is there a ‘plan’ for having some target ElementType.TYPE level @NotNull annotation (or even package level) that I could use on Java API’s?

In particular I note that @NotNull from org.jetbrains:annotations:15.0 … does not target ElementType.TYPE but maybe I have missed something?

Thanks, Rob.


#2

It looks like 1.1.4 has something that will help here. See https://blog.jetbrains.com/kotlin/2017/08/kotlin-1-1-4-is-out/ (search for “Package-default nullability annotations”):

Kotlin supports package-default nullability annotations (such as JSR-305’s @ParametersAreNonnullByDefault and the @NonNullApi annotation introduced in Spring Framework 5.0)…the support for such annotations is off by default, and needs to be enabled by passing the -Xjsr305-annotations=enable command line option to the compiler.


#3

Thanks Ted, that is what I was looking for.

So yes maybe we will see some changes in the future wrt ‘out of the box’ default behavior. This sent me towards the slightly different path of “biting the bullet” and adding annotations to get the IDE behavior I desired by default without any compiler options.

Interestingly I went with Class retention on the javax.annotation @Nonnull and @Nullable. This was a bit more work but I really just wanted it to work out of the box. I went to class retention to avoid adding the dependency to users of the library. I’ll review after the next point release of Kotlin and see if a better option becomes available or if I missed something.

As an aside I was using the org.jetbrains annotations but in Kotlin with IDE auto-complete I additionally got @NotNull in my Kotlin source (which seemed like a bug to me - sorry, haven’t logged it yet) but that prompted me to migrate over to javax.annotation.Nonnull.

I need to come back to this in a month or two and review.

Cheers, Rob.


#4

Do these annotations affect importing methods?

When I’ve tried it with FastAdapter, importing

    override fun bindView(holder: VH, payloads: MutableList<Any>?) {
        super.bindView(holder, payloads)
    }

still resulted in a nullable parameter as shown above, even though lint recognizes that super’s payload is nonnull.

I have enabled the flag to enable the annotation.


#5

What is the canonical jar (= maven/gradle dependency) to get the @Nonnull class from? I’ve also posted this question on StackOverflow. There are many maven dependencies that contain it. There’s a small majority for findbugs JSR-305’s jar, but it doesn’t look like spring-core gets it from there.


#6

So there wasn’t really a usable one at the time so I created my own. io.ebean : ebean-jsr305 : 1.1

I use it with provided scope.