diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/builtins/LoadBuiltinsTest.java b/compiler/tests/org/jetbrains/kotlin/serialization/builtins/LoadBuiltinsTest.java index 75c92741004..49d3d103812 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/builtins/LoadBuiltinsTest.java +++ b/compiler/tests/org/jetbrains/kotlin/serialization/builtins/LoadBuiltinsTest.java @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy; import org.jetbrains.kotlin.resolve.lazy.KotlinTestWithEnvironment; import org.jetbrains.kotlin.resolve.lazy.LazyResolveTestUtil; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; +import org.jetbrains.kotlin.serialization.deserialization.AdditionalSupertypes; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.kotlin.test.JetTestUtils; @@ -51,7 +52,7 @@ import java.util.List; import java.util.regex.Pattern; import static kotlin.KotlinPackage.single; -import static org.jetbrains.kotlin.builtins.BuiltinsPackage.createBuiltInPackageFragmentProvider; +import static org.jetbrains.kotlin.builtins.BuiltInsPackageFragmentProviderKt.createBuiltInPackageFragmentProvider; import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME; import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAMES; @@ -109,6 +110,7 @@ public class LoadBuiltinsTest extends KotlinTestWithEnvironment { PackageFragmentProvider packageFragmentProvider = createBuiltInPackageFragmentProvider( storageManager, builtInsModule, BUILT_INS_PACKAGE_FQ_NAMES, new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule), + AdditionalSupertypes.None.INSTANCE$, new Function1() { @Override public InputStream invoke(String path) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BuiltInClassesAreSerializableOnJvm.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BuiltInClassesAreSerializableOnJvm.kt new file mode 100644 index 00000000000..b5f55aa61e5 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BuiltInClassesAreSerializableOnJvm.kt @@ -0,0 +1,84 @@ +/* + * 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.load.kotlin + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.platform.JvmBuiltIns +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.scopes.JetScope +import org.jetbrains.kotlin.serialization.deserialization.AdditionalSupertypes +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor +import org.jetbrains.kotlin.types.DelegatingType +import org.jetbrains.kotlin.types.JetType +import java.io.Serializable + +class BuiltInClassesAreSerializableOnJvm( + private val moduleDescriptor: ModuleDescriptor +) : AdditionalSupertypes { + + private val mockSerializableType = createMockJavaIoSerializableType() + + private fun createMockJavaIoSerializableType(): JetType { + val mockJavaIoPackageFragment = object : PackageFragmentDescriptorImpl(moduleDescriptor, FqName("java.io")) { + override fun getMemberScope() = JetScope.Empty + } + + //NOTE: can't reference anyType right away, because this is sometimes called when JvmBuiltIns are initializing + val superTypes = listOf(object : DelegatingType() { + override fun getDelegate(): JetType { + return JvmBuiltIns.Instance.anyType + } + }) + + val mockSerializableClass = ClassDescriptorImpl( + mockJavaIoPackageFragment, Name.identifier("Serializable"), Modality.ABSTRACT, superTypes, SourceElement.NO_SOURCE + ) + + mockSerializableClass.initialize(JetScope.Empty, emptySet(), null) + return mockSerializableClass.defaultType + } + + override fun forClass(classDescriptor: DeserializedClassDescriptor): Collection { + if (isSerializableInJava(classDescriptor.fqNameSafe)) { + return listOf(mockSerializableType) + } + else return listOf() + } + + private fun isSerializableInJava(classFqName: FqName): Boolean { + val fqNameUnsafe = classFqName.toUnsafe() + if (fqNameUnsafe == KotlinBuiltIns.FQ_NAMES.array || KotlinBuiltIns.isPrimitiveArray(fqNameUnsafe)) { + return true + } + val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqNameUnsafe) ?: return false + val classViaReflection = try { + Class.forName(javaClassId.asSingleFqName().asString()) + } + catch (e: ClassNotFoundException) { + return false + } + return Serializable::class.java.isAssignableFrom(classViaReflection) + } +} \ No newline at end of file diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt index fccd8698100..13e68ea0f8e 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt @@ -39,9 +39,9 @@ public class DeserializationComponentsForJava( init { val localClassResolver = LocalClassResolverImpl() components = DeserializationComponents( - storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, - localClassResolver, errorReporter, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, - JavaTypeCapabilitiesLoader + storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider, localClassResolver, + errorReporter, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY, JavaTypeCapabilitiesLoader, + additionalSupertypes = BuiltInClassesAreSerializableOnJvm(moduleDescriptor) ) localClassResolver.setDeserializationComponents(components) } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt index d618fe04af9..1cd0ae7034c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.platform import org.jetbrains.kotlin.builtins.BuiltInsInitializer import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.load.kotlin.BuiltInClassesAreSerializableOnJvm +import org.jetbrains.kotlin.serialization.deserialization.AdditionalSupertypes class JvmBuiltIns private constructor() : KotlinBuiltIns() { companion object { @@ -29,4 +31,8 @@ class JvmBuiltIns private constructor() : KotlinBuiltIns() { val Instance: KotlinBuiltIns get() = initializer.get() } + + override fun getAdditionalSupertypesProvider(): AdditionalSupertypes { + return BuiltInClassesAreSerializableOnJvm(builtInsModule) + } } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 3b75eafb3d7..d1eeece6382 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.scopes.JetScope; +import org.jetbrains.kotlin.serialization.deserialization.AdditionalSupertypes; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.JetTypeChecker; @@ -54,7 +55,7 @@ public abstract class KotlinBuiltIns { BuiltinsPackage.getKOTLIN_REFLECT_FQ_NAME() ); - private final ModuleDescriptorImpl builtInsModule; + protected final ModuleDescriptorImpl builtInsModule; private final BuiltinsPackageFragment builtinsPackageFragment; private final BuiltinsPackageFragment annotationPackageFragment; @@ -73,6 +74,7 @@ public abstract class KotlinBuiltIns { PackageFragmentProvider packageFragmentProvider = BuiltinsPackage.createBuiltInPackageFragmentProvider( storageManager, builtInsModule, BUILT_INS_PACKAGE_FQ_NAMES, new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule), + getAdditionalSupertypesProvider(), new Function1() { @Override public InputStream invoke(String path) { @@ -95,6 +97,11 @@ public abstract class KotlinBuiltIns { } } + @NotNull + protected AdditionalSupertypes getAdditionalSupertypesProvider() { + return AdditionalSupertypes.None.INSTANCE$; + } + private void makePrimitive(@NotNull PrimitiveType primitiveType) { JetType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString()); JetType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString()); @@ -646,6 +653,10 @@ public abstract class KotlinBuiltIns { return primitiveJetTypeToJetArrayType.get(jetType); } + public static boolean isPrimitiveArray(@NotNull FqNameUnsafe arrayFqName) { + return getPrimitiveTypeByArrayClassFqName(arrayFqName) != null; + } + @Nullable public static PrimitiveType getPrimitiveTypeByFqName(@NotNull FqNameUnsafe primitiveClassFqName) { return FQ_NAMES.fqNameToPrimitiveType.get(primitiveClassFqName); diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt index bcba0a8b473..2640addaeaa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/builtInsPackageFragmentProvider.kt @@ -29,6 +29,7 @@ public fun createBuiltInPackageFragmentProvider( module: ModuleDescriptor, packageFqNames: Set, classDescriptorFactory: ClassDescriptorFactory, + additionalSupertypes: AdditionalSupertypes = AdditionalSupertypes.None, loadResource: (String) -> InputStream? ): PackageFragmentProvider { val packageFragments = packageFqNames.map { fqName -> @@ -47,7 +48,8 @@ public fun createBuiltInPackageFragmentProvider( localClassResolver, ErrorReporter.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, - classDescriptorFactory + classDescriptorFactory, + additionalSupertypes = additionalSupertypes ) localClassResolver.setDeserializationComponents(components) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AdditionalSupertypes.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AdditionalSupertypes.kt new file mode 100644 index 00000000000..898c7779fab --- /dev/null +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/AdditionalSupertypes.kt @@ -0,0 +1,28 @@ +/* + * 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.serialization.deserialization + +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor +import org.jetbrains.kotlin.types.JetType + +interface AdditionalSupertypes { + fun forClass(classDescriptor: DeserializedClassDescriptor): Collection + + object None : AdditionalSupertypes { + override fun forClass(classDescriptor: DeserializedClassDescriptor): Collection = emptyList() + } +} \ No newline at end of file diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt index 3f92332d039..d8931332998 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/context.kt @@ -25,16 +25,17 @@ import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.storage.StorageManager public class DeserializationComponents( - public val storageManager: StorageManager, - public val moduleDescriptor: ModuleDescriptor, - public val classDataFinder: ClassDataFinder, - public val annotationAndConstantLoader: AnnotationAndConstantLoader, AnnotationWithTarget>, - public val packageFragmentProvider: PackageFragmentProvider, - public val localClassResolver: LocalClassResolver, - public val errorReporter: ErrorReporter, - public val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer, - public val fictitiousClassDescriptorFactory: ClassDescriptorFactory, - public val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE + val storageManager: StorageManager, + val moduleDescriptor: ModuleDescriptor, + val classDataFinder: ClassDataFinder, + val annotationAndConstantLoader: AnnotationAndConstantLoader, AnnotationWithTarget>, + val packageFragmentProvider: PackageFragmentProvider, + val localClassResolver: LocalClassResolver, + val errorReporter: ErrorReporter, + val flexibleTypeCapabilitiesDeserializer: FlexibleTypeCapabilitiesDeserializer, + val fictitiousClassDescriptorFactory: ClassDescriptorFactory, + val typeCapabilitiesLoader: TypeCapabilitiesLoader = TypeCapabilitiesLoader.NONE, + val additionalSupertypes: AdditionalSupertypes = AdditionalSupertypes.None ) { public val classDeserializer: ClassDeserializer = ClassDeserializer(this) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt index 69eb7b6daeb..2a4b2afa8c3 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt @@ -149,6 +149,8 @@ public class DeserializedClassDescriptor( } } + result.addAll(c.components.additionalSupertypes.forClass(this)) + if (unresolved.isNotEmpty()) { c.components.errorReporter.reportIncompleteHierarchy(this, unresolved.map(DeserializedType::getPresentableText)) }