Evolve DSL for defining enhanced nullability info for known JDK functions. Enhance nullability for java.util.Optional.
This commit is contained in:
+129
-14
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.java.typeEnhancement
|
package org.jetbrains.kotlin.load.java.typeEnhancement
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||||
import org.jetbrains.kotlin.load.kotlin.signatures
|
import org.jetbrains.kotlin.load.kotlin.signatures
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType.BOOLEAN
|
||||||
|
|
||||||
class TypeEnhancementInfo(val map: Map<Int, JavaTypeQualifiers>) {
|
class TypeEnhancementInfo(val map: Map<Int, JavaTypeQualifiers>) {
|
||||||
constructor(vararg pairs: Pair<Int, JavaTypeQualifiers>) : this(mapOf(*pairs))
|
constructor(vararg pairs: Pair<Int, JavaTypeQualifiers>) : this(mapOf(*pairs))
|
||||||
@@ -27,20 +30,132 @@ class PredefinedFunctionEnhancementInfo(
|
|||||||
val parametersInfo: List<TypeEnhancementInfo?> = emptyList()
|
val parametersInfo: List<TypeEnhancementInfo?> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
private val NOT_NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = false)
|
/** Type is always nullable: `T?` */
|
||||||
|
private val NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NULLABLE, null, isNotNullTypeParameter = false)
|
||||||
|
/** Nullability depends on substitution, but the type is not platform: `T` */
|
||||||
|
private val NOT_PLATFORM = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = false)
|
||||||
|
/** Type is always non-nullable: `T & Any` */
|
||||||
|
private val NOT_NULLABLE = JavaTypeQualifiers(NullabilityQualifier.NOT_NULL, null, isNotNullTypeParameter = true)
|
||||||
|
|
||||||
val PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE = signatures {
|
val PREDEFINED_FUNCTION_ENHANCEMENT_INFO_BY_SIGNATURE = signatures {
|
||||||
mapOf(
|
val JLObject = javaLang("Object")
|
||||||
signature(javaUtil("Iterator"), "forEachRemaining(Ljava/util/function/Consumer;)V") to
|
val JFPredicate = javaFunction("Predicate")
|
||||||
PredefinedFunctionEnhancementInfo(
|
val JFConsumer = javaFunction("Consumer")
|
||||||
parametersInfo = listOf(
|
val JFBiFunction = javaFunction("BiFunction")
|
||||||
TypeEnhancementInfo(
|
val JFFunction = javaFunction("Function")
|
||||||
0 to NOT_NULLABLE,
|
val JUOptional = javaUtil("Optional")
|
||||||
1 to NOT_NULLABLE
|
|
||||||
)
|
enhancement {
|
||||||
)
|
forClass(javaUtil("Iterator")) {
|
||||||
),
|
function("forEachRemaining") {
|
||||||
signature("java/util/function/Consumer", "accept(Ljava/lang/Object;)V") to
|
parameter(JFConsumer, NOT_PLATFORM, NOT_PLATFORM)
|
||||||
PredefinedFunctionEnhancementInfo(parametersInfo = listOf(TypeEnhancementInfo(0 to NOT_NULLABLE)))
|
}
|
||||||
)
|
}
|
||||||
|
forClass(javaUtil("Collection")) {
|
||||||
|
function("removeIf") {
|
||||||
|
parameter(JFPredicate, NOT_PLATFORM, NOT_PLATFORM)
|
||||||
|
returns(BOOLEAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(javaUtil("Map")) {
|
||||||
|
function("merge") {
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
parameter(JLObject, NOT_NULLABLE)
|
||||||
|
parameter(JFBiFunction, NOT_PLATFORM, NOT_NULLABLE, NOT_NULLABLE, NULLABLE)
|
||||||
|
returns(JLObject, NULLABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(JFConsumer) {
|
||||||
|
function("accept") {
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(JFPredicate) {
|
||||||
|
function("test") {
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
returns(BOOLEAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(JFFunction) {
|
||||||
|
function("apply") {
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
returns(JLObject, NOT_PLATFORM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(JFBiFunction) {
|
||||||
|
function("apply") {
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
parameter(JLObject, NOT_PLATFORM)
|
||||||
|
returns(JLObject, NOT_PLATFORM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forClass(JUOptional) {
|
||||||
|
function("empty") {
|
||||||
|
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
|
||||||
|
}
|
||||||
|
function("of") {
|
||||||
|
parameter(JLObject, NOT_NULLABLE)
|
||||||
|
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
|
||||||
|
}
|
||||||
|
function("ofNullable") {
|
||||||
|
parameter(JLObject, NULLABLE)
|
||||||
|
returns(JUOptional, NOT_PLATFORM, NOT_NULLABLE)
|
||||||
|
}
|
||||||
|
function("get") {
|
||||||
|
returns(JLObject, NOT_NULLABLE)
|
||||||
|
}
|
||||||
|
function("ifPresent") {
|
||||||
|
parameter(JFConsumer, NOT_PLATFORM, NOT_NULLABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inline fun enhancement(block: SignatureEnhancementBuilder.() -> Unit): Map<String, PredefinedFunctionEnhancementInfo>
|
||||||
|
= SignatureEnhancementBuilder().apply(block).build()
|
||||||
|
|
||||||
|
private class SignatureEnhancementBuilder {
|
||||||
|
private val signatures = mutableMapOf<String, PredefinedFunctionEnhancementInfo>()
|
||||||
|
|
||||||
|
inline fun forClass(internalName: String, block: ClassEnhancementBuilder.() -> Unit) =
|
||||||
|
ClassEnhancementBuilder(internalName).block()
|
||||||
|
|
||||||
|
inner class ClassEnhancementBuilder(val className: String) {
|
||||||
|
fun function(name: String, block: FunctionEnhancementBuilder.() -> Unit) {
|
||||||
|
signatures += FunctionEnhancementBuilder(name).apply(block).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class FunctionEnhancementBuilder(val functionName: String) {
|
||||||
|
private val parameters = mutableListOf<Pair<String, TypeEnhancementInfo?>>()
|
||||||
|
private var returnType: Pair<String, TypeEnhancementInfo?> = "V" to null
|
||||||
|
|
||||||
|
fun parameter(type: String, vararg pairs: Pair<Int, JavaTypeQualifiers>) {
|
||||||
|
parameters += type to
|
||||||
|
if (pairs.isEmpty()) null else TypeEnhancementInfo(*pairs)
|
||||||
|
}
|
||||||
|
fun parameter(type: String, vararg qualifiers: JavaTypeQualifiers) {
|
||||||
|
parameters += type to
|
||||||
|
if (qualifiers.isEmpty()) null else TypeEnhancementInfo(qualifiers.withIndex().associateBy({it.index}, {it.value}))
|
||||||
|
}
|
||||||
|
fun returns(type: String, vararg pairs: Pair<Int, JavaTypeQualifiers>) {
|
||||||
|
returnType = type to TypeEnhancementInfo(*pairs)
|
||||||
|
}
|
||||||
|
fun returns(type: String, vararg qualifiers: JavaTypeQualifiers) {
|
||||||
|
returnType = type to TypeEnhancementInfo(qualifiers.withIndex().associateBy({it.index}, {it.value}))
|
||||||
|
}
|
||||||
|
fun returns(type: JvmPrimitiveType) {
|
||||||
|
returnType = type.desc to null
|
||||||
|
}
|
||||||
|
fun build() = with (SignatureBuildingComponents) {
|
||||||
|
signature(className, jvmDescriptor(functionName, parameters.map { it.first }, returnType.first)) to
|
||||||
|
PredefinedFunctionEnhancementInfo(returnType.second, parameters.map { it.second })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(): Map<String, PredefinedFunctionEnhancementInfo> = signatures
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
@@ -25,6 +25,7 @@ inline fun <T> signatures(block: SignatureBuildingComponents.() -> T) = with(Sig
|
|||||||
object SignatureBuildingComponents {
|
object SignatureBuildingComponents {
|
||||||
fun javaLang(name: String) = "java/lang/$name"
|
fun javaLang(name: String) = "java/lang/$name"
|
||||||
fun javaUtil(name: String) = "java/util/$name"
|
fun javaUtil(name: String) = "java/util/$name"
|
||||||
|
fun javaFunction(name: String) = "java/util/function/$name"
|
||||||
|
|
||||||
fun constructors(vararg signatures: String) = signatures.map { "<init>($it)V" }.toTypedArray()
|
fun constructors(vararg signatures: String) = signatures.map { "<init>($it)V" }.toTypedArray()
|
||||||
|
|
||||||
@@ -36,4 +37,11 @@ object SignatureBuildingComponents {
|
|||||||
fun signature(classDescriptor: ClassDescriptor, jvmDescriptor: String) = signature(classDescriptor.internalName, jvmDescriptor)
|
fun signature(classDescriptor: ClassDescriptor, jvmDescriptor: String) = signature(classDescriptor.internalName, jvmDescriptor)
|
||||||
fun signature(classId: ClassId, jvmDescriptor: String) = signature(classId.internalName, jvmDescriptor)
|
fun signature(classId: ClassId, jvmDescriptor: String) = signature(classId.internalName, jvmDescriptor)
|
||||||
fun signature(internalName: String, jvmDescriptor: String) = internalName + "." + jvmDescriptor
|
fun signature(internalName: String, jvmDescriptor: String) = internalName + "." + jvmDescriptor
|
||||||
|
|
||||||
|
fun jvmDescriptor(name: String, vararg parameters: String, ret: String = "V") =
|
||||||
|
jvmDescriptor(name, parameters.asList(), ret)
|
||||||
|
fun jvmDescriptor(name: String, parameters: List<String>, ret: String = "V") =
|
||||||
|
"$name(${parameters.joinToString("") { escapeClassName(it) }})${escapeClassName(internalName = ret)}"
|
||||||
|
|
||||||
|
private fun escapeClassName(internalName: String) = if (internalName.length > 1) "L$internalName;" else internalName
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user