Refactor RuntimeTypeMapper, extract IntrinsicObjects-related behavior
Make it similar to other JavaToKotlinClassMapBuilder implementations to be able to get rid of that inheritance
This commit is contained in:
@@ -1,14 +1,12 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class Klass
|
class Klass
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val x = Klass::class
|
assertEquals("Klass", Klass::class.simpleName)
|
||||||
if (x.simpleName != "Klass") return "Fail x: ${x.simpleName}"
|
assertEquals("Date", java.util.Date::class.simpleName)
|
||||||
|
assertEquals("Kind", kotlin.jvm.internal.KotlinSyntheticClass.Kind::class.simpleName)
|
||||||
val y = java.util.Date::class
|
assertEquals("Void", java.lang.Void::class.simpleName)
|
||||||
if (y.simpleName != "Date") return "Fail y: ${y.simpleName}"
|
|
||||||
|
|
||||||
val z = kotlin.jvm.internal.KotlinSyntheticClass.Kind::class
|
|
||||||
if (z.simpleName != "Kind") return "Fail z: ${z.simpleName}"
|
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -58,10 +58,9 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val type = c.storageManager.createLazyValue {
|
private val type = c.storageManager.createLazyValue {
|
||||||
val fqName = fqName()
|
val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
|
||||||
if (fqName == null) return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
|
val annotationClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName)
|
||||||
val annotationClass = JavaToKotlinClassMap.INSTANCE.mapKotlinClass(fqName, TypeUsage.MEMBER_SIGNATURE_INVARIANT)
|
?: javaAnnotation.resolve()?.let { javaClass -> c.moduleClassResolver.resolveClass(javaClass) }
|
||||||
?: javaAnnotation.resolve()?.let { javaClass -> c.moduleClassResolver.resolveClass(javaClass) }
|
|
||||||
annotationClass?.getDefaultType() ?: ErrorUtils.createErrorType(fqName.asString())
|
annotationClass?.getDefaultType() ?: ErrorUtils.createErrorType(fqName.asString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -146,7 +146,7 @@ class LazyJavaTypeResolver(
|
|||||||
return c.reflectionTypes.kClass
|
return c.reflectionTypes.kClass
|
||||||
}
|
}
|
||||||
|
|
||||||
val javaToKotlinClassMap = JavaToKotlinClassMap.INSTANCE
|
val javaToKotlin = JavaToKotlinClassMap.INSTANCE
|
||||||
|
|
||||||
val howThisTypeIsUsedEffectively = when {
|
val howThisTypeIsUsedEffectively = when {
|
||||||
attr.flexibility == FLEXIBLE_LOWER_BOUND -> MEMBER_SIGNATURE_COVARIANT
|
attr.flexibility == FLEXIBLE_LOWER_BOUND -> MEMBER_SIGNATURE_COVARIANT
|
||||||
@@ -154,13 +154,19 @@ class LazyJavaTypeResolver(
|
|||||||
|
|
||||||
// This case has to be checked before isMarkedReadOnly/isMarkedMutable, because those two are slow
|
// This case has to be checked before isMarkedReadOnly/isMarkedMutable, because those two are slow
|
||||||
// not mapped, we don't care about being marked mutable/read-only
|
// not mapped, we don't care about being marked mutable/read-only
|
||||||
javaToKotlinClassMap.mapPlatformClass(fqName).isEmpty() -> attr.howThisTypeIsUsed
|
javaToKotlin.mapPlatformClass(fqName).isEmpty() -> attr.howThisTypeIsUsed
|
||||||
|
|
||||||
// Read (possibly external) annotations
|
// Read (possibly external) annotations
|
||||||
else -> attr.howThisTypeIsUsedAccordingToAnnotations
|
else -> attr.howThisTypeIsUsedAccordingToAnnotations
|
||||||
}
|
}
|
||||||
|
|
||||||
return javaToKotlinClassMap.mapKotlinClass(fqName, howThisTypeIsUsedEffectively)
|
if (howThisTypeIsUsedEffectively == MEMBER_SIGNATURE_COVARIANT || howThisTypeIsUsedEffectively == SUPERTYPE) {
|
||||||
|
javaToKotlin.mapJavaToKotlinCovariant(fqName)?.let { mutableCollectionDescriptor ->
|
||||||
|
return mutableCollectionDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return javaToKotlin.mapJavaToKotlin(fqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isConstructorTypeParameter(): Boolean {
|
private fun isConstructorTypeParameter(): Boolean {
|
||||||
|
|||||||
+8
-10
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
import org.jetbrains.kotlin.builtins.PrimitiveType;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage;
|
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
@@ -49,16 +48,15 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor mapKotlinClass(@NotNull FqName fqName, @NotNull TypeUsage typeUsage) {
|
public ClassDescriptor mapJavaToKotlin(@NotNull FqName fqName) {
|
||||||
if (typeUsage == TypeUsage.MEMBER_SIGNATURE_COVARIANT || typeUsage == TypeUsage.SUPERTYPE) {
|
|
||||||
ClassDescriptor descriptor = classDescriptorMapForCovariantPositions.get(fqName);
|
|
||||||
if (descriptor != null) {
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return classDescriptorMap.get(fqName);
|
return classDescriptorMap.get(fqName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public ClassDescriptor mapJavaToKotlinCovariant(@NotNull FqName fqName) {
|
||||||
|
return classDescriptorMapForCovariantPositions.get(fqName);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static FqName fqNameByClass(@NotNull Class<?> clazz) {
|
private static FqName fqNameByClass(@NotNull Class<?> clazz) {
|
||||||
return new FqName(clazz.getCanonicalName());
|
return new FqName(clazz.getCanonicalName());
|
||||||
@@ -92,8 +90,8 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<ClassDescriptor> mapPlatformClass(@NotNull FqName fqName) {
|
public Collection<ClassDescriptor> mapPlatformClass(@NotNull FqName fqName) {
|
||||||
ClassDescriptor kotlinAnalog = classDescriptorMap.get(fqName);
|
ClassDescriptor kotlinAnalog = mapJavaToKotlin(fqName);
|
||||||
ClassDescriptor kotlinCovariantAnalog = classDescriptorMapForCovariantPositions.get(fqName);
|
ClassDescriptor kotlinCovariantAnalog = mapJavaToKotlinCovariant(fqName);
|
||||||
List<ClassDescriptor> descriptors = new ArrayList<ClassDescriptor>(2);
|
List<ClassDescriptor> descriptors = new ArrayList<ClassDescriptor>(2);
|
||||||
if (kotlinAnalog != null) {
|
if (kotlinAnalog != null) {
|
||||||
descriptors.add(kotlinAnalog);
|
descriptors.add(kotlinAnalog);
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
object InverseIntrinsicObjectsMapping {
|
||||||
|
private val map = linkedMapOf<FqName, ClassDescriptor>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (descriptor in KotlinBuiltIns.getInstance().getBuiltInsPackageFragment().getMemberScope().getAllDescriptors()) {
|
||||||
|
val companion = (descriptor as? ClassDescriptor)?.getCompanionObjectDescriptor() ?: continue
|
||||||
|
IntrinsicObjects.mapType(companion)?.let { fqName ->
|
||||||
|
map[fqName] = companion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a FQ name of an internal JVM class representing a built-in companion object to the relevant Kotlin descriptor,
|
||||||
|
* e.g. [kotlin.jvm.internal.StringCompanionObject] -> class descriptor of [kotlin.String.Companion]
|
||||||
|
*/
|
||||||
|
fun mapJvmClassToKotlinDescriptor(javaFqName: FqName): ClassDescriptor? = map[javaFqName]
|
||||||
|
}
|
||||||
@@ -17,27 +17,26 @@
|
|||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects
|
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||||
import org.jetbrains.kotlin.load.java.structure.reflect.desc
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMapBuilder
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMapBuilder
|
||||||
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMapBuilder.Direction.BOTH
|
||||||
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMapBuilder.Direction.KOTLIN_TO_JAVA
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import kotlin.reflect.KotlinReflectionInternalError
|
|
||||||
|
|
||||||
object RuntimeTypeMapper : JavaToKotlinClassMapBuilder() {
|
object RuntimeTypeMapper : JavaToKotlinClassMapBuilder() {
|
||||||
private val kotlinArrayClassId = KotlinBuiltIns.getInstance().getArray().classId
|
|
||||||
|
|
||||||
private val kotlinFqNameToJvmDesc = linkedMapOf<FqName, String>()
|
private val kotlinFqNameToJvmDesc = linkedMapOf<FqName, String>()
|
||||||
private val jvmDescToKotlinClassId = linkedMapOf<String, ClassId>()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
init()
|
init()
|
||||||
@@ -48,43 +47,26 @@ object RuntimeTypeMapper : JavaToKotlinClassMapBuilder() {
|
|||||||
val builtIns = KotlinBuiltIns.getInstance()
|
val builtIns = KotlinBuiltIns.getInstance()
|
||||||
|
|
||||||
for (type in JvmPrimitiveType.values()) {
|
for (type in JvmPrimitiveType.values()) {
|
||||||
val primitiveType = type.getPrimitiveType()
|
recordKotlinToJvm(builtIns.getPrimitiveClassDescriptor(type.getPrimitiveType()), type.getDesc())
|
||||||
val primitiveClassDescriptor = builtIns.getPrimitiveClassDescriptor(primitiveType)
|
|
||||||
|
|
||||||
recordKotlinToJvm(primitiveClassDescriptor, type.getDesc())
|
|
||||||
recordKotlinToJvm(builtIns.getPrimitiveArrayClassDescriptor(primitiveType), "[" + type.getDesc())
|
|
||||||
|
|
||||||
recordJvmToKotlin(ClassId.topLevel(type.getWrapperFqName()).desc, primitiveClassDescriptor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recordKotlinToJvm(kotlinDescriptor: ClassDescriptor, jvmDesc: String) {
|
private fun recordKotlinToJvm(kotlinDescriptor: ClassDescriptor, jvmDesc: String) {
|
||||||
kotlinFqNameToJvmDesc[DescriptorUtils.getFqNameSafe(kotlinDescriptor)] = jvmDesc
|
kotlinFqNameToJvmDesc[DescriptorUtils.getFqNameSafe(kotlinDescriptor)] = jvmDesc
|
||||||
recordJvmToKotlin(jvmDesc, kotlinDescriptor)
|
|
||||||
|
|
||||||
val companionObject = kotlinDescriptor.getCompanionObjectDescriptor()
|
|
||||||
if (companionObject != null) {
|
|
||||||
val runtimeCompanionFqName = IntrinsicObjects.mapType(companionObject)
|
|
||||||
?: throw KotlinReflectionInternalError("Failed to map intrinsic companion of $kotlinDescriptor")
|
|
||||||
recordKotlinToJvm(companionObject, ClassId.topLevel(runtimeCompanionFqName).desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun recordJvmToKotlin(jvmDesc: String, kotlinDescriptor: ClassDescriptor) {
|
|
||||||
jvmDescToKotlinClassId[jvmDesc] = kotlinDescriptor.classId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun register(javaClass: Class<*>, kotlinDescriptor: ClassDescriptor, direction: JavaToKotlinClassMapBuilder.Direction) {
|
override fun register(javaClass: Class<*>, kotlinDescriptor: ClassDescriptor, direction: JavaToKotlinClassMapBuilder.Direction) {
|
||||||
// TODO: use direction correctly
|
if (direction == BOTH || direction == KOTLIN_TO_JAVA) {
|
||||||
recordKotlinToJvm(kotlinDescriptor, javaClass.classId.desc)
|
recordKotlinToJvm(kotlinDescriptor, javaClass.classId.desc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun register(javaClass: Class<*>, kotlinDescriptor: ClassDescriptor, kotlinMutableDescriptor: ClassDescriptor) {
|
override fun register(javaClass: Class<*>, kotlinDescriptor: ClassDescriptor, kotlinMutableDescriptor: ClassDescriptor) {
|
||||||
// TODO: readonly collection mapping just rewrites the mutable one, improve readability here
|
|
||||||
register(javaClass, kotlinMutableDescriptor, JavaToKotlinClassMapBuilder.Direction.BOTH)
|
register(javaClass, kotlinMutableDescriptor, JavaToKotlinClassMapBuilder.Direction.BOTH)
|
||||||
register(javaClass, kotlinDescriptor, JavaToKotlinClassMapBuilder.Direction.BOTH)
|
register(javaClass, kotlinDescriptor, JavaToKotlinClassMapBuilder.Direction.BOTH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this logic must be shared with JetTypeMapper
|
||||||
fun mapTypeToJvmDesc(type: JetType): String {
|
fun mapTypeToJvmDesc(type: JetType): String {
|
||||||
val classifier = type.getConstructor().getDeclarationDescriptor()
|
val classifier = type.getConstructor().getDeclarationDescriptor()
|
||||||
if (classifier is TypeParameterDescriptor) {
|
if (classifier is TypeParameterDescriptor) {
|
||||||
@@ -106,21 +88,50 @@ object RuntimeTypeMapper : JavaToKotlinClassMapBuilder() {
|
|||||||
return if (TypeUtils.isNullableType(type)) ClassId.topLevel(jvmType.getWrapperFqName()).desc else jvmType.getDesc()
|
return if (TypeUtils.isNullableType(type)) ClassId.topLevel(jvmType.getWrapperFqName()).desc else jvmType.getDesc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(fqNameUnsafe)?.let { primitiveType ->
|
||||||
|
return "[" + JvmPrimitiveType.get(primitiveType).getDesc()
|
||||||
|
}
|
||||||
|
|
||||||
if (fqNameUnsafe.isSafe()) {
|
if (fqNameUnsafe.isSafe()) {
|
||||||
kotlinFqNameToJvmDesc[fqNameUnsafe.toSafe()]?.let { return it }
|
kotlinFqNameToJvmDesc[fqNameUnsafe.toSafe()]?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (classDescriptor.isCompanionObject()) {
|
||||||
|
IntrinsicObjects.mapType(classDescriptor)?.let { fqName ->
|
||||||
|
return ClassId.topLevel(fqName).desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return classDescriptor.classId.desc
|
return classDescriptor.classId.desc
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mapJvmClassToKotlinClassId(klass: Class<*>): ClassId {
|
fun mapJvmClassToKotlinClassId(klass: Class<*>): ClassId {
|
||||||
if (klass.isArray() && !klass.getComponentType().isPrimitive()) {
|
if (klass.isArray()) {
|
||||||
return kotlinArrayClassId
|
klass.getComponentType().primitiveType?.let {
|
||||||
|
return KotlinBuiltIns.getInstance().getPrimitiveArrayClassDescriptor(it).classId
|
||||||
|
}
|
||||||
|
return ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.array.toSafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
return jvmDescToKotlinClassId[klass.desc] ?: klass.classId
|
klass.primitiveType?.let {
|
||||||
|
return KotlinBuiltIns.getInstance().getPrimitiveClassDescriptor(it).classId
|
||||||
|
}
|
||||||
|
|
||||||
|
val classId = klass.classId
|
||||||
|
if (!classId.isLocal()) {
|
||||||
|
val fqName = classId.asSingleFqName()
|
||||||
|
val kotlinClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName)
|
||||||
|
kotlinClass?.let { return it.classId }
|
||||||
|
|
||||||
|
InverseIntrinsicObjectsMapping.mapJvmClassToKotlinDescriptor(fqName)?.let { return it.classId }
|
||||||
|
}
|
||||||
|
|
||||||
|
return classId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Class<*>.primitiveType: PrimitiveType?
|
||||||
|
get() = if (isPrimitive()) JvmPrimitiveType.get(getSimpleName()).getPrimitiveType() else null
|
||||||
|
|
||||||
private val ClassId.desc: String
|
private val ClassId.desc: String
|
||||||
get() = "L${JvmClassName.byClassId(this).getInternalName()};"
|
get() = "L${JvmClassName.byClassId(this).getInternalName()};"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user