Map intrinsic companion objects in JavaToKotlinClassMap

Get rid of multiple usages of IntrinsicObjects where JavaToKotlinClassMap was
already used, simplify code, and support loading of *CompanionObject as Kotlin
built-in companions from Java code.

Also fix a small bug where Boolean was considered a class with an intrinsic
companion in IntrinsicObjects, although it was not
This commit is contained in:
Alexander Udalov
2015-04-23 19:33:37 +03:00
parent 987206bf95
commit d2cd7b00bb
12 changed files with 62 additions and 111 deletions
@@ -17,7 +17,7 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects;
import org.jetbrains.kotlin.builtins.CompanionObjectMapping;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
@@ -34,7 +34,7 @@ public class FieldInfo {
throw new UnsupportedOperationException("Can't create singleton field for class: " + classDescriptor);
}
if (isNonCompanionObject(classDescriptor) || IntrinsicObjects.INSTANCE$.hasMappingToObject(classDescriptor)) {
if (isNonCompanionObject(classDescriptor) || CompanionObjectMapping.hasMappingToObject(classDescriptor)) {
Type type = typeMapper.mapType(classDescriptor);
return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true);
}
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
@@ -339,16 +338,6 @@ public class JetTypeMapper {
}
if (descriptor instanceof ClassDescriptor) {
FqName companionObjectMappedFqName = IntrinsicObjects.mapType((ClassDescriptor) descriptor);
if (companionObjectMappedFqName != null) {
Type asmType = asmTypeByFqNameWithoutInnerClasses(companionObjectMappedFqName);
if (signatureVisitor != null) {
signatureVisitor.writeAsmType(asmType);
}
return asmType;
}
Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
AsmTypes.JAVA_CLASS_TYPE :
computeAsmType((ClassDescriptor) descriptor.getOriginal());
@@ -0,0 +1,10 @@
package test;
import kotlin.jvm.internal.*;
public interface IntrinsicCompanionObject {
void testInt(IntCompanionObject i);
void testChar(CharCompanionObject c);
void testString(StringCompanionObject s);
void testEnum(EnumCompanionObject e);
}
@@ -0,0 +1,8 @@
package test
public trait IntrinsicCompanionObject {
public abstract fun testChar(/*0*/ p0: kotlin.Char.Companion!): kotlin.Unit
public abstract fun testEnum(/*0*/ p0: kotlin.Enum.Companion!): kotlin.Unit
public abstract fun testInt(/*0*/ p0: kotlin.Int.Companion!): kotlin.Unit
public abstract fun testString(/*0*/ p0: kotlin.String.Companion!): kotlin.Unit
}
@@ -145,6 +145,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTestCompiledJava(fileName);
}
@TestMetadata("IntrinsicCompanionObject.java")
public void testIntrinsicCompanionObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/IntrinsicCompanionObject.java");
doTestCompiledJava(fileName);
}
@TestMetadata("MethodReferencesOuterClassTP.java")
public void testMethodReferencesOuterClassTP() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/MethodReferencesOuterClassTP.java");
@@ -3151,6 +3151,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
doTest(fileName);
}
@TestMetadata("IntrinsicCompanionObject.java")
public void testIntrinsicCompanionObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/IntrinsicCompanionObject.java");
doTest(fileName);
}
@TestMetadata("MethodReferencesOuterClassTP.java")
public void testMethodReferencesOuterClassTP() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/MethodReferencesOuterClassTP.java");
@@ -1,35 +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.builtins.jvm
import org.jetbrains.kotlin.builtins.CompanionObjectMapping
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import kotlin.platform.platformStatic
public object IntrinsicObjects : CompanionObjectMapping() {
private val kotlinJvmInternal = FqName("kotlin.jvm.internal")
public platformStatic fun mapType(classDescriptor: ClassDescriptor): FqName? {
if (!hasMappingToObject(classDescriptor)) return null
val containingDeclaration = classDescriptor.getContainingDeclaration()
val name = Name.identifier(containingDeclaration.getName().asString() + "CompanionObject")
return kotlinJvmInternal.child(name)
}
}
@@ -18,6 +18,7 @@ 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.PrimitiveType;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
@@ -67,6 +68,12 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
add(ClassId.topLevel(jvmType.getWrapperFqName()), builtIns.getPrimitiveClassDescriptor(jvmType.getPrimitiveType()));
}
for (ClassDescriptor descriptor : CompanionObjectMapping.allClassesWithIntrinsicCompanions()) {
ClassDescriptor companion = descriptor.getCompanionObjectDescriptor();
assert companion != null : "No companion object found for " + descriptor;
add(ClassId.topLevel(new FqName("kotlin.jvm.internal." + descriptor.getName().asString() + "CompanionObject")), companion);
}
addJavaToKotlin(classId(Deprecated.class), builtIns.getDeprecatedAnnotation());
addKotlinToJava(classId(Void.class), builtIns.getNothing());
@@ -77,6 +84,7 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
* java.lang.String -> kotlin.String
* java.lang.Deprecated -> kotlin.deprecated
* java.lang.Integer -> kotlin.Int
* kotlin.jvm.internal.IntCompanionObject -> kotlin.Int.Companion
* java.util.List -> kotlin.List
* java.lang.Void -> null
*/
@@ -100,6 +108,7 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
* 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
*/
@@ -18,16 +18,26 @@ package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.Collections
import kotlin.platform.platformStatic
public abstract class CompanionObjectMapping {
public fun hasMappingToObject(classDescriptor: ClassDescriptor): Boolean {
if (!DescriptorUtils.isCompanionObject(classDescriptor)) return false
public object CompanionObjectMapping {
private val classes = linkedSetOf<ClassDescriptor>()
val containingDeclaration = classDescriptor.getContainingDeclaration()
if (containingDeclaration !is ClassDescriptor) return false
init {
val builtIns = KotlinBuiltIns.getInstance()
for (type in PrimitiveType.NUMBER_TYPES) {
classes.add(builtIns.getPrimitiveClassDescriptor(type))
}
classes.add(builtIns.getString())
classes.add(builtIns.getEnum())
}
return KotlinBuiltIns.isPrimitiveType(containingDeclaration.getDefaultType()) ||
KotlinBuiltIns.getInstance().getString() == containingDeclaration ||
KotlinBuiltIns.getInstance().getEnum() == containingDeclaration
public platformStatic fun allClassesWithIntrinsicCompanions(): Set<ClassDescriptor> =
Collections.unmodifiableSet(classes)
public platformStatic fun hasMappingToObject(classDescriptor: ClassDescriptor): Boolean {
return DescriptorUtils.isCompanionObject(classDescriptor) &&
classDescriptor.getContainingDeclaration() in classes
}
}
@@ -1,41 +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 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]
}
@@ -18,7 +18,6 @@ package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.jvm.IntrinsicObjects
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.load.java.structure.reflect.classId
@@ -60,12 +59,6 @@ object RuntimeTypeMapper {
JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName)?.let { return it.desc }
if (classDescriptor.isCompanionObject()) {
IntrinsicObjects.mapType(classDescriptor)?.let { fqName ->
return ClassId.topLevel(fqName).desc
}
}
return classDescriptor.classId.desc
}
@@ -83,11 +76,7 @@ object RuntimeTypeMapper {
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 }
JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(classId.asSingleFqName())?.let { return it.classId }
}
return classId
@@ -35,9 +35,9 @@ class DefaultClassObjectIntrinsic(val fqName: FqName, val moduleName: String): O
}
}
public class ObjectIntrinsics : CompanionObjectMapping() {
public class ObjectIntrinsics {
public fun getIntrinsic(classDescriptor: ClassDescriptor): ObjectIntrinsic {
if (!hasMappingToObject(classDescriptor)) return NO_OBJECT_INTRINSIC
if (!CompanionObjectMapping.hasMappingToObject(classDescriptor)) return NO_OBJECT_INTRINSIC
val containingDeclaration = classDescriptor.getContainingDeclaration()
val name = Name.identifier(containingDeclaration.getName().asString() + "CompanionObject")