J2K JavaToKotlinClassMap

This commit is contained in:
Pavel V. Talanov
2017-05-03 17:58:01 +03:00
parent 6701eb70fb
commit 40561dabed
24 changed files with 236 additions and 264 deletions
@@ -51,7 +51,7 @@ class LazyJavaAnnotationDescriptor(
private val type = c.storageManager.createLazyValue {
val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
val annotationClass = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(fqName, c.module.builtIns)
val annotationClass = JavaToKotlinClassMap.mapJavaToKotlin(fqName, c.module.builtIns)
?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) }
?: createTypeForMissingDependencies(fqName)
annotationClass.defaultType
@@ -148,7 +148,7 @@ class JavaTypeResolver(
return c.components.reflectionTypes.kClass
}
val javaToKotlin = JavaToKotlinClassMap.INSTANCE
val javaToKotlin = JavaToKotlinClassMap
val howThisTypeIsUsedEffectively = when {
attr.flexibility == FLEXIBLE_LOWER_BOUND -> MEMBER_SIGNATURE_COVARIANT
@@ -185,7 +185,7 @@ class JavaTypeResolver(
fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false
if (!typeArguments.lastOrNull().isSuperWildcard()) return false
val mutableLastParameterVariance = JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(readOnlyContainer)
val mutableLastParameterVariance = JavaToKotlinClassMap.convertReadOnlyToMutable(readOnlyContainer)
.typeConstructor.parameters.lastOrNull()?.variance ?: return false
return mutableLastParameterVariance != OUT_VARIANCE
@@ -155,7 +155,7 @@ private fun ClassifierDescriptor.enhanceMutability(qualifiers: JavaTypeQualifier
if (!position.shouldEnhance()) return this.noChange()
if (this !is ClassDescriptor) return this.noChange() // mutability is not applicable for type parameters
val mapping = JavaToKotlinClassMap.INSTANCE
val mapping = JavaToKotlinClassMap
when (qualifiers.mutability) {
READ_ONLY -> {
@@ -55,7 +55,7 @@ private fun KotlinType.extractQualifiers(): JavaTypeQualifiers {
asFlexibleType().let { Pair(it.lowerBound, it.upperBound) }
else Pair(this, this)
val mapping = JavaToKotlinClassMap.INSTANCE
val mapping = JavaToKotlinClassMap
return JavaTypeQualifiers(
if (lower.isMarkedNullable) NULLABLE else if (!upper.isMarkedNullable) NOT_NULL else null,
if (mapping.isReadOnly(lower)) READ_ONLY else if (mapping.isMutable(upper)) MUTABLE else null,
@@ -56,7 +56,7 @@ open class JvmBuiltInsSettings(
deferredOwnerModuleDescriptor: () -> ModuleDescriptor,
isAdditionalBuiltInsFeatureSupported: () -> Boolean
) : AdditionalClassPartsProvider, PlatformDependentDeclarationFilter {
private val j2kClassMap = JavaToKotlinClassMap.INSTANCE
private val j2kClassMap = JavaToKotlinClassMap
private val ownerModuleDescriptor: ModuleDescriptor by lazy(deferredOwnerModuleDescriptor)
private val isAdditionalBuiltInsFeatureSupported: Boolean by lazy(isAdditionalBuiltInsFeatureSupported)
@@ -326,7 +326,7 @@ open class JvmBuiltInsSettings(
if (isArrayOrPrimitiveArray(fqName)) {
return true
}
val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName) ?: return false
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(fqName) ?: return false
val classViaReflection = try {
Class.forName(javaClassId.asSingleFqName().asString())
}
@@ -80,7 +80,7 @@ internal fun CallableDescriptor.computeJvmSignature(): String? = signatures {
internal val ClassDescriptor.internalName: String
get() {
JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqNameSafe.toUnsafe())?.let {
JavaToKotlinClassMap.mapKotlinToJava(fqNameSafe.toUnsafe())?.let {
return JvmClassName.byClassId(it).internalName
}
@@ -89,7 +89,7 @@ internal val ClassDescriptor.internalName: String
internal val ClassId.internalName: String
get() {
return JvmClassName.byClassId(JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(asSingleFqName().toUnsafe()) ?: this).internalName
return JvmClassName.byClassId(JavaToKotlinClassMap.mapKotlinToJava(asSingleFqName().toUnsafe()) ?: this).internalName
}
private fun StringBuilder.appendErasedType(type: KotlinType) {
@@ -209,7 +209,7 @@ private fun <T : Any> mapBuiltInType(
return typeFactory.createFromString("[" + JvmPrimitiveType.get(arrayElementType).desc)
}
val classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName)
val classId = JavaToKotlinClassMap.mapKotlinToJava(fqName)
if (classId != null) {
return typeFactory.createObjectType(JvmClassName.byClassId(classId, typeMappingConfiguration).internalName)
}
@@ -1,239 +0,0 @@
/*
* 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 org.jetbrains.kotlin.platform;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.CompanionObjectMapping;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.name.*;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
import java.lang.annotation.Annotation;
import java.util.*;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getFqNameUnsafe;
public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
public static final JavaToKotlinClassMap INSTANCE = new JavaToKotlinClassMap();
private final Map<FqNameUnsafe, ClassId> javaToKotlin = new HashMap<FqNameUnsafe, ClassId>();
private final Map<FqNameUnsafe, ClassId> kotlinToJava = new HashMap<FqNameUnsafe, ClassId>();
private final Map<FqNameUnsafe, FqName> mutableToReadOnly = new HashMap<FqNameUnsafe, FqName>();
private final Map<FqNameUnsafe, FqName> readOnlyToMutable = new HashMap<FqNameUnsafe, FqName>();
private JavaToKotlinClassMap() {
addTopLevel(Object.class, FQ_NAMES.any);
addTopLevel(String.class, FQ_NAMES.string);
addTopLevel(CharSequence.class, FQ_NAMES.charSequence);
addTopLevel(Throwable.class, FQ_NAMES.throwable);
addTopLevel(Cloneable.class, FQ_NAMES.cloneable);
addTopLevel(Number.class, FQ_NAMES.number);
addTopLevel(Comparable.class, FQ_NAMES.comparable);
addTopLevel(Enum.class, FQ_NAMES._enum);
addTopLevel(Annotation.class, FQ_NAMES.annotation);
addMutableReadOnlyPair(Iterable.class, ClassId.topLevel(FQ_NAMES.iterable), FQ_NAMES.mutableIterable);
addMutableReadOnlyPair(Iterator.class, ClassId.topLevel(FQ_NAMES.iterator), FQ_NAMES.mutableIterator);
addMutableReadOnlyPair(Collection.class, ClassId.topLevel(FQ_NAMES.collection), FQ_NAMES.mutableCollection);
addMutableReadOnlyPair(List.class, ClassId.topLevel(FQ_NAMES.list), FQ_NAMES.mutableList);
addMutableReadOnlyPair(Set.class, ClassId.topLevel(FQ_NAMES.set), FQ_NAMES.mutableSet);
addMutableReadOnlyPair(ListIterator.class, ClassId.topLevel(FQ_NAMES.listIterator), FQ_NAMES.mutableListIterator);
ClassId mapClassId = ClassId.topLevel(FQ_NAMES.map);
addMutableReadOnlyPair(Map.class, mapClassId, FQ_NAMES.mutableMap);
addMutableReadOnlyPair(Map.Entry.class, mapClassId.createNestedClassId(FQ_NAMES.mapEntry.shortName()), FQ_NAMES.mutableMapEntry);
for (JvmPrimitiveType jvmType : JvmPrimitiveType.values()) {
add(
ClassId.topLevel(jvmType.getWrapperFqName()),
ClassId.topLevel(KotlinBuiltIns.getPrimitiveFqName(jvmType.getPrimitiveType()))
);
}
for (ClassId classId : CompanionObjectMapping.INSTANCE.allClassesWithIntrinsicCompanions()) {
add(ClassId.topLevel(
new FqName("kotlin.jvm.internal." + classId.getShortClassName().asString() + "CompanionObject")),
classId.createNestedClassId(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT));
}
// TODO: support also functions with >= 23 parameters
for (int i = 0; i < 23; i++) {
add(ClassId.topLevel(new FqName("kotlin.jvm.functions.Function" + i)), KotlinBuiltIns.getFunctionClassId(i));
FunctionClassDescriptor.Kind kFunction = FunctionClassDescriptor.Kind.KFunction;
String kFun = kFunction.getPackageFqName() + "." + kFunction.getClassNamePrefix();
addKotlinToJava(new FqName(kFun + i), ClassId.topLevel(new FqName(kFun)));
}
addKotlinToJava(FQ_NAMES.nothing.toSafe(), classId(Void.class));
}
/**
* E.g.
* java.lang.String -> kotlin.String
* java.lang.Integer -> kotlin.Int
* kotlin.jvm.internal.IntCompanionObject -> kotlin.Int.Companion
* java.util.List -> kotlin.List
* java.util.Map.Entry -> kotlin.Map.Entry
* java.lang.Void -> null
* kotlin.jvm.functions.Function3 -> kotlin.Function3
*/
@Nullable
public ClassId mapJavaToKotlin(@NotNull FqName fqName) {
return javaToKotlin.get(fqName.toUnsafe());
}
@Nullable
public ClassDescriptor mapJavaToKotlin(@NotNull FqName fqName, @NotNull KotlinBuiltIns builtIns) {
ClassId kotlinClassId = mapJavaToKotlin(fqName);
return kotlinClassId != null ? builtIns.getBuiltInClassByFqName(kotlinClassId.asSingleFqName()) : null;
}
/**
* E.g.
* kotlin.Throwable -> java.lang.Throwable
* kotlin.Int -> java.lang.Integer
* kotlin.Int.Companion -> kotlin.jvm.internal.IntCompanionObject
* kotlin.Nothing -> java.lang.Void
* kotlin.IntArray -> null
* kotlin.Function3 -> kotlin.jvm.functions.Function3
* kotlin.reflect.KFunction3 -> kotlin.reflect.KFunction
*/
@Nullable
public ClassId mapKotlinToJava(@NotNull FqNameUnsafe kotlinFqName) {
return kotlinToJava.get(kotlinFqName);
}
private void addMutableReadOnlyPair(
@NotNull Class<?> javaClass,
@NotNull ClassId kotlinReadOnlyClassId,
@NotNull FqName kotlinMutableFqName
) {
ClassId javaClassId = classId(javaClass);
add(javaClassId, kotlinReadOnlyClassId);
addKotlinToJava(kotlinMutableFqName, javaClassId);
FqName kotlinReadOnlyFqName = kotlinReadOnlyClassId.asSingleFqName();
mutableToReadOnly.put(kotlinMutableFqName.toUnsafe(), kotlinReadOnlyFqName);
readOnlyToMutable.put(kotlinReadOnlyFqName.toUnsafe(), kotlinMutableFqName);
}
private void add(@NotNull ClassId javaClassId, @NotNull ClassId kotlinClassId) {
addJavaToKotlin(javaClassId, kotlinClassId);
addKotlinToJava(kotlinClassId.asSingleFqName(), javaClassId);
}
private void addTopLevel(@NotNull Class<?> javaClass, @NotNull FqNameUnsafe kotlinFqName) {
addTopLevel(javaClass, kotlinFqName.toSafe());
}
private void addTopLevel(@NotNull Class<?> javaClass, @NotNull FqName kotlinFqName) {
add(classId(javaClass), ClassId.topLevel(kotlinFqName));
}
private void addJavaToKotlin(@NotNull ClassId javaClassId, @NotNull ClassId kotlinClassId) {
javaToKotlin.put(javaClassId.asSingleFqName().toUnsafe(), kotlinClassId);
}
private void addKotlinToJava(@NotNull FqName kotlinFqNameUnsafe, @NotNull ClassId javaClassId) {
kotlinToJava.put(kotlinFqNameUnsafe.toUnsafe(), javaClassId);
}
@NotNull
private static ClassId classId(@NotNull Class<?> clazz) {
assert !clazz.isPrimitive() && !clazz.isArray() : "Invalid class: " + clazz;
Class<?> outer = clazz.getDeclaringClass();
return outer == null
? ClassId.topLevel(new FqName(clazz.getCanonicalName()))
: classId(outer).createNestedClassId(Name.identifier(clazz.getSimpleName()));
}
public boolean isJavaPlatformClass(@NotNull FqName fqName) {
return mapJavaToKotlin(fqName) != null;
}
@NotNull
public Collection<ClassDescriptor> mapPlatformClass(@NotNull FqName fqName, @NotNull KotlinBuiltIns builtIns) {
ClassDescriptor kotlinAnalog = mapJavaToKotlin(fqName, builtIns);
if (kotlinAnalog == null) return Collections.emptySet();
FqName kotlinMutableAnalogFqName = readOnlyToMutable.get(getFqNameUnsafe(kotlinAnalog));
if (kotlinMutableAnalogFqName == null) return Collections.singleton(kotlinAnalog);
return Arrays.asList(kotlinAnalog, builtIns.getBuiltInClassByFqName(kotlinMutableAnalogFqName));
}
@Override
@NotNull
public Collection<ClassDescriptor> mapPlatformClass(@NotNull ClassDescriptor classDescriptor) {
FqNameUnsafe className = DescriptorUtils.getFqName(classDescriptor);
return className.isSafe()
? mapPlatformClass(className.toSafe(), getBuiltIns(classDescriptor))
: Collections.<ClassDescriptor>emptySet();
}
public boolean isMutable(@NotNull ClassDescriptor mutable) {
return mutableToReadOnly.containsKey(DescriptorUtils.getFqName(mutable));
}
public boolean isMutable(@NotNull KotlinType type) {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
return classDescriptor != null && isMutable(classDescriptor);
}
public boolean isReadOnly(@NotNull ClassDescriptor readOnly) {
return readOnlyToMutable.containsKey(DescriptorUtils.getFqName(readOnly));
}
public boolean isReadOnly(@NotNull KotlinType type) {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
return classDescriptor != null && isReadOnly(classDescriptor);
}
@NotNull
public ClassDescriptor convertMutableToReadOnly(@NotNull ClassDescriptor mutable) {
return convertToOppositeMutability(mutable, mutableToReadOnly, "mutable");
}
@NotNull
private static ClassDescriptor convertToOppositeMutability(
@NotNull ClassDescriptor descriptor,
@NotNull Map<FqNameUnsafe, FqName> map,
@NotNull String mutabilityKindName
) {
FqName oppositeClassFqName = map.get(DescriptorUtils.getFqName(descriptor));
if (oppositeClassFqName == null) {
throw new IllegalArgumentException("Given class " + descriptor + " is not a " + mutabilityKindName + " collection");
}
return getBuiltIns(descriptor).getBuiltInClassByFqName(oppositeClassFqName);
}
@NotNull
public ClassDescriptor convertReadOnlyToMutable(@NotNull ClassDescriptor readOnly) {
return convertToOppositeMutability(readOnly, readOnlyToMutable, "read-only");
}
}
@@ -0,0 +1,211 @@
/*
* 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 org.jetbrains.kotlin.platform
import org.jetbrains.kotlin.builtins.CompanionObjectMapping
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import java.util.*
object JavaToKotlinClassMap : PlatformToKotlinClassMap {
private val javaToKotlin = HashMap<FqNameUnsafe, ClassId>()
private val kotlinToJava = HashMap<FqNameUnsafe, ClassId>()
private val mutableToReadOnly = HashMap<FqNameUnsafe, FqName>()
private val readOnlyToMutable = HashMap<FqNameUnsafe, FqName>()
init {
addTopLevel(Any::class.java, FQ_NAMES.any)
addTopLevel(String::class.java, FQ_NAMES.string)
addTopLevel(CharSequence::class.java, FQ_NAMES.charSequence)
addTopLevel(Throwable::class.java, FQ_NAMES.throwable)
addTopLevel(Cloneable::class.java, FQ_NAMES.cloneable)
addTopLevel(Number::class.java, FQ_NAMES.number)
addTopLevel(Comparable::class.java, FQ_NAMES.comparable)
addTopLevel(Enum::class.java, FQ_NAMES._enum)
addTopLevel(Annotation::class.java, FQ_NAMES.annotation)
addMutableReadOnlyPair(Iterable::class.java, ClassId.topLevel(FQ_NAMES.iterable), FQ_NAMES.mutableIterable)
addMutableReadOnlyPair(Iterator::class.java, ClassId.topLevel(FQ_NAMES.iterator), FQ_NAMES.mutableIterator)
addMutableReadOnlyPair(Collection::class.java, ClassId.topLevel(FQ_NAMES.collection), FQ_NAMES.mutableCollection)
addMutableReadOnlyPair(List::class.java, ClassId.topLevel(FQ_NAMES.list), FQ_NAMES.mutableList)
addMutableReadOnlyPair(Set::class.java, ClassId.topLevel(FQ_NAMES.set), FQ_NAMES.mutableSet)
addMutableReadOnlyPair(ListIterator::class.java, ClassId.topLevel(FQ_NAMES.listIterator), FQ_NAMES.mutableListIterator)
val mapClassId = ClassId.topLevel(FQ_NAMES.map)
addMutableReadOnlyPair(Map::class.java, mapClassId, FQ_NAMES.mutableMap)
addMutableReadOnlyPair(Map.Entry::class.java, mapClassId.createNestedClassId(FQ_NAMES.mapEntry.shortName()), FQ_NAMES.mutableMapEntry)
for (jvmType in JvmPrimitiveType.values()) {
add(ClassId.topLevel(jvmType.wrapperFqName),
ClassId.topLevel(KotlinBuiltIns.getPrimitiveFqName(jvmType.primitiveType)))
}
for (classId in CompanionObjectMapping.allClassesWithIntrinsicCompanions()) {
add(ClassId.topLevel(FqName("kotlin.jvm.internal." + classId.shortClassName.asString() + "CompanionObject")),
classId.createNestedClassId(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT))
}
// TODO: support also functions with >= 23 parameters
for (i in 0..22) {
add(ClassId.topLevel(FqName("kotlin.jvm.functions.Function" + i)), KotlinBuiltIns.getFunctionClassId(i))
val kFunction = FunctionClassDescriptor.Kind.KFunction
val kFun = kFunction.packageFqName.toString() + "." + kFunction.classNamePrefix
addKotlinToJava(FqName(kFun + i), ClassId.topLevel(FqName(kFun)))
}
addKotlinToJava(FQ_NAMES.nothing.toSafe(), classId(Void::class.java))
}
/**
* E.g.
* java.lang.String -> kotlin.String
* java.lang.Integer -> kotlin.Int
* kotlin.jvm.internal.IntCompanionObject -> kotlin.Int.Companion
* java.util.List -> kotlin.List
* java.util.Map.Entry -> kotlin.Map.Entry
* java.lang.Void -> null
* kotlin.jvm.functions.Function3 -> kotlin.Function3
*/
fun mapJavaToKotlin(fqName: FqName): ClassId? {
return javaToKotlin[fqName.toUnsafe()]
}
fun mapJavaToKotlin(fqName: FqName, builtIns: KotlinBuiltIns): ClassDescriptor? {
val kotlinClassId = mapJavaToKotlin(fqName)
return if (kotlinClassId != null) builtIns.getBuiltInClassByFqName(kotlinClassId.asSingleFqName()) else null
}
/**
* E.g.
* kotlin.Throwable -> java.lang.Throwable
* kotlin.Int -> java.lang.Integer
* kotlin.Int.Companion -> kotlin.jvm.internal.IntCompanionObject
* kotlin.Nothing -> java.lang.Void
* kotlin.IntArray -> null
* kotlin.Function3 -> kotlin.jvm.functions.Function3
* kotlin.reflect.KFunction3 -> kotlin.reflect.KFunction
*/
fun mapKotlinToJava(kotlinFqName: FqNameUnsafe): ClassId? {
return kotlinToJava[kotlinFqName]
}
private fun addMutableReadOnlyPair(
javaClass: Class<*>,
kotlinReadOnlyClassId: ClassId,
kotlinMutableFqName: FqName
) {
val javaClassId = classId(javaClass)
add(javaClassId, kotlinReadOnlyClassId)
addKotlinToJava(kotlinMutableFqName, javaClassId)
val kotlinReadOnlyFqName = kotlinReadOnlyClassId.asSingleFqName()
mutableToReadOnly.put(kotlinMutableFqName.toUnsafe(), kotlinReadOnlyFqName)
readOnlyToMutable.put(kotlinReadOnlyFqName.toUnsafe(), kotlinMutableFqName)
}
private fun add(javaClassId: ClassId, kotlinClassId: ClassId) {
addJavaToKotlin(javaClassId, kotlinClassId)
addKotlinToJava(kotlinClassId.asSingleFqName(), javaClassId)
}
private fun addTopLevel(javaClass: Class<*>, kotlinFqName: FqNameUnsafe) {
addTopLevel(javaClass, kotlinFqName.toSafe())
}
private fun addTopLevel(javaClass: Class<*>, kotlinFqName: FqName) {
add(classId(javaClass), ClassId.topLevel(kotlinFqName))
}
private fun addJavaToKotlin(javaClassId: ClassId, kotlinClassId: ClassId) {
javaToKotlin.put(javaClassId.asSingleFqName().toUnsafe(), kotlinClassId)
}
private fun addKotlinToJava(kotlinFqNameUnsafe: FqName, javaClassId: ClassId) {
kotlinToJava.put(kotlinFqNameUnsafe.toUnsafe(), javaClassId)
}
fun isJavaPlatformClass(fqName: FqName): Boolean = mapJavaToKotlin(fqName) != null
fun mapPlatformClass(fqName: FqName, builtIns: KotlinBuiltIns): Collection<ClassDescriptor> {
val kotlinAnalog = mapJavaToKotlin(fqName, builtIns) ?: return emptySet()
val kotlinMutableAnalogFqName = readOnlyToMutable[kotlinAnalog.fqNameUnsafe] ?: return setOf(kotlinAnalog)
return Arrays.asList(kotlinAnalog, builtIns.getBuiltInClassByFqName(kotlinMutableAnalogFqName))
}
override fun mapPlatformClass(classDescriptor: ClassDescriptor): Collection<ClassDescriptor> {
val className = DescriptorUtils.getFqName(classDescriptor)
return if (className.isSafe)
mapPlatformClass(className.toSafe(), classDescriptor.builtIns)
else
emptySet<ClassDescriptor>()
}
fun isMutable(mutable: ClassDescriptor): Boolean = mutableToReadOnly.containsKey(DescriptorUtils.getFqName(mutable))
fun isMutable(type: KotlinType): Boolean {
val classDescriptor = TypeUtils.getClassDescriptor(type)
return classDescriptor != null && isMutable(classDescriptor)
}
fun isReadOnly(readOnly: ClassDescriptor): Boolean = readOnlyToMutable.containsKey(DescriptorUtils.getFqName(readOnly))
fun isReadOnly(type: KotlinType): Boolean {
val classDescriptor = TypeUtils.getClassDescriptor(type)
return classDescriptor != null && isReadOnly(classDescriptor)
}
fun convertMutableToReadOnly(mutable: ClassDescriptor): ClassDescriptor {
return convertToOppositeMutability(mutable, mutableToReadOnly, "mutable")
}
fun convertReadOnlyToMutable(readOnly: ClassDescriptor): ClassDescriptor {
return convertToOppositeMutability(readOnly, readOnlyToMutable, "read-only")
}
private fun classId(clazz: Class<*>): ClassId {
assert(!clazz.isPrimitive && !clazz.isArray) { "Invalid class: " + clazz }
val outer = clazz.declaringClass
return if (outer == null)
ClassId.topLevel(FqName(clazz.canonicalName))
else
classId(outer).createNestedClassId(Name.identifier(clazz.simpleName))
}
private fun convertToOppositeMutability(
descriptor: ClassDescriptor,
map: Map<FqNameUnsafe, FqName>,
mutabilityKindName: String
): ClassDescriptor {
val oppositeClassFqName = map[DescriptorUtils.getFqName(descriptor)] ?: throw IllegalArgumentException("Given class $descriptor is not a $mutabilityKindName collection")
return descriptor.builtIns.getBuiltInClassByFqName(oppositeClassFqName)
}
}
@@ -42,7 +42,7 @@ object ClassMapperLite {
if (simpleName == KotlinBuiltIns.FQ_NAMES.unit.shortName().asString()) return "V"
}
val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(classId.asSingleFqName().toUnsafe())
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(classId.asSingleFqName().toUnsafe())
if (javaClassId != null) {
return "L" + javaClassId.asString().replace('.', '$') + ";"
}