Home > Software design >  Platform types and jsr-305 annotations when using kotlin with project reactor
Platform types and jsr-305 annotations when using kotlin with project reactor

Time:02-12

I am using project reactor with kotlin. As expected, since i am writing kotlin code that calls java code, all type signatures from project reactor's operators are showing up as platform types. e.g.

//here i is inferred as Int!
Mono.just(1).map { i -> i   1 }

Reading through project reactor's documentation, it seems like theres a way to assert that all types are non nullable and to have the types be inferred as non nullable types. https://projectreactor.io/docs/core/release/reference/#kotlin-null-safety

Kotlin support for JSR 305 annotations and Reactor nullability annotations provide null-safety for the whole Reactor API to Kotlin developers, with the advantage of dealing with null-related issues at compile time.

I have tried using the suggested compiler option with no luck. Using the following kotlin configuration, the type of i is still showing up as Int! while i would now expect it to be Int.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.6.10"
    application
}

group = "me.stef"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    testImplementation(kotlin("test"))
    implementation("io.projectreactor:reactor-core:3.4.14")
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        jvmTarget = "1.8"
        freeCompilerArgs = listOf("-Xjsr305=strict")
    }
}

application {
    mainClass.set("MainKt")
}

I am using the intelliJ IDEA Ultimate version 2021.3.2 with the kotlin plugin version 213-1.6.10-release-961-IJ6777.52

I am aware that i can use explicit type annotations to turn the platform types into nullable or non null types, but i would like avoid that if possible.

So my questions are:

  1. Am i correctly interpreting the documentation in understanding that there's indeed a way to enforce non nullable types when using project reactor with kotlin?
  2. If i have understood correctly, and the jsr305 compiler option is the way to achieve my goal, what could i be doing wrong?
  3. If thats not the way to achieve my goal, how can i do it?
  4. Could it be a problem with intellij?

CodePudding user response:

Actually the behaviour is by design because @NonNullApi which is applied to a package from where you are calling the method (map), doesn't have type use default qualifier, but only METHOD and PARAMETER. In particular, it means that the Kotlin compiler doesn't enhance types inside type argument positions, but only whole types in return type and value parameter positions.

It can be proved with the following code:

fun main() {
    // useless unsafe call before `get()` is reported because
    // the Kotlin compiler already enhanced the return type of `blockOptional` to not-null
    Mono.just(1).blockOptional()?.get()
}

In your specific case, the lambda's value parameter i is mapped to T type argument of Function in map declaration which corresponds to type use position. That's why the Kotlin compiler doesn't enhance this type.

Note that the Kotlin compiler supports enhancing types from Java by default nullability annotations (including on a package ones) in type use positions. See the following compiler test.

So maybe it makes sense to create a feature request for reactor to expand scope of its NonNullApi annotation to type use positions.

  • Related