Improve toString of platform types created by typeOf

In the stdlib implementation, render "!" if the type is only
nullability-flexible. Otherwise, render "($lower..$upper)".

Note that full kotlin-reflect has a much more complicated logic (see
`DescriptorRendererImpl.renderFlexibleType`) that renders things like
`(Mutable)List` and so on. It is not a goal of the stdlib implementation
to replicate all of that, since it requires copying a large amount of
code, namely the entirety of `JavaToKotlinClassMap` to map Java class
names to Kotlin.
This commit is contained in:
Alexander Udalov
2021-07-08 22:34:43 +02:00
parent ddfa94e7e9
commit a7e48c3af1
10 changed files with 157 additions and 12 deletions
@@ -15,12 +15,11 @@ fun check(expected: String, actual: KType) {
}
fun box(): String {
// String representation of platform types does not differ from non-nullable types in the stdlib implementation (without reflect).
check("java.lang.String", returnTypeOf { J.nullabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.mutabilityFlexible() })
check("java.util.List<java.lang.String>", returnTypeOf { J.bothFlexible() })
check("java.lang.String!", returnTypeOf { J.nullabilityFlexible() })
check("java.util.List<java.lang.String!>", returnTypeOf { J.mutabilityFlexible() })
check("java.util.List<java.lang.String!>!", returnTypeOf { J.bothFlexible() })
// However, type flexibility affects equality! Platform type is neither nullable nor non-nullable.
// Type flexibility affects equality! Platform type is neither nullable nor non-nullable.
val platform = returnTypeOf { J.nullabilityFlexible() }
if (platform == returnTypeOf { J.nullable() }) return "Fail: platform type should not be equal to nullable type"
if (platform == returnTypeOf { J.notNull() }) return "Fail: platform type should not be equal to non-nullable type"
@@ -26,8 +26,7 @@ fun box(): String {
check("test.C<kotlin.Nothing?>", typeOf<C<Nothing?>>())
check("kotlin.Nothing?", nothingBound<Nothing?>())
// String representation of platform types does not differ from non-nullable types in the stdlib implementation (without reflect).
check("test.C<kotlin.Nothing>", returnTypeOf { C(J.platformType<Nothing>()) })
check("test.C<kotlin.Nothing!>", returnTypeOf { C(J.platformType<Nothing>()) })
// Such type's classifier is still Void::class, until KT-15518 is fixed.
// TODO: support a special KClass instance for Nothing (KT-15518).
@@ -0,0 +1,43 @@
// !API_VERSION: LATEST
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
fun check(expected: String, actual: KType) {
assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
}
fun box(): String {
check("int", returnTypeOf { J.primitive() })
check("java.lang.Integer!", returnTypeOf { J.wrapper() })
check("java.lang.Integer?", returnTypeOf { J.nullableWrapper() })
check("java.lang.Integer", returnTypeOf { J.notNullWrapper() })
return "OK"
}
inline fun <reified T> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class J {
public static int primitive() { return 0; }
public static Integer wrapper() { return 0; }
@Nullable
public static Integer nullableWrapper() { return 0; }
@NotNull
public static Integer notNullWrapper() { return 0; }
}
@@ -18,10 +18,10 @@ fun check(expected: String, actual: KType) {
class C<T, U : Number>
fun box(): String {
check("test.C<java.lang.Object?, java.lang.Number>", returnTypeOf { J.raw() })
check("test.C<java.lang.Object?, java.lang.Number>", returnTypeOf { J.rawNotNull() })
check("java.util.List<java.lang.Object?>", returnTypeOf { J.rawList() })
check("java.util.Map<java.lang.Object?, java.lang.Object?>", returnTypeOf { J.rawNotNullMap() })
check("(test.C<java.lang.Object?, java.lang.Number>..test.C<*, *>?)", returnTypeOf { J.raw() })
check("(test.C<java.lang.Object?, java.lang.Number>..test.C<*, *>)", returnTypeOf { J.rawNotNull() })
check("(java.util.List<java.lang.Object?>..java.util.List<*>?)", returnTypeOf { J.rawList() })
check("(java.util.Map<java.lang.Object?, java.lang.Object?>..java.util.Map<*, *>)", returnTypeOf { J.rawNotNullMap() })
return "OK"
}
@@ -0,0 +1,43 @@
// !API_VERSION: LATEST
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: box.kt
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
fun check(expected: String, actual: KType) {
assertEquals(expected, actual.toString())
}
fun box(): String {
check("kotlin.Int", returnTypeOf { J.primitive() })
check("kotlin.Int!", returnTypeOf { J.wrapper() })
check("kotlin.Int?", returnTypeOf { J.nullableWrapper() })
check("kotlin.Int", returnTypeOf { J.notNullWrapper() })
return "OK"
}
inline fun <reified T> returnTypeOf(block: () -> T) =
typeOf<T>()
// FILE: J.java
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class J {
public static int primitive() { return 0; }
public static Integer wrapper() { return 0; }
@Nullable
public static Integer nullableWrapper() { return 0; }
@NotNull
public static Integer notNullWrapper() { return 0; }
}