Serialize metadata for Cloneable and discard it during deserialization
#KT-16358 Fixed
This commit is contained in:
+17
-1
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.serialization.builtins
|
|||||||
|
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
||||||
|
import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.*
|
import org.jetbrains.kotlin.cli.common.messages.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
@@ -26,12 +28,16 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
|||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.serialization.MetadataSerializer
|
import org.jetbrains.kotlin.serialization.MetadataSerializer
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(dependOnOldBuiltIns) {
|
class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(dependOnOldBuiltIns) {
|
||||||
@@ -88,11 +94,21 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(depe
|
|||||||
fqName ->
|
fqName ->
|
||||||
val packageView = module.getPackage(fqName)
|
val packageView = module.getPackage(fqName)
|
||||||
PackageSerializer(
|
PackageSerializer(
|
||||||
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS),
|
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
|
||||||
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
|
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
|
||||||
packageView.fqName,
|
packageView.fqName,
|
||||||
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
|
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName))
|
||||||
).run()
|
).run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serialize metadata for kotlin.Cloneable manually for compatibility with kotlin-reflect 1.0 which expects this metadata to be there.
|
||||||
|
// Since Kotlin 1.1, we always discard this class during deserialization (see ClassDeserializer.kt).
|
||||||
|
private fun createCloneable(module: ModuleDescriptor): ClassDescriptor {
|
||||||
|
val factory = JvmBuiltInClassDescriptorFactory(LockBasedStorageManager.NO_LOCKS, module) {
|
||||||
|
EmptyPackageFragmentDescriptor(module, KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
|
||||||
|
}
|
||||||
|
return factory.createClass(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe()))
|
||||||
|
?: error("Could not create kotlin.Cloneable in $module")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import kotlin.<!UNRESOLVED_REFERENCE!>Cloneable<!>
|
||||||
|
|
||||||
|
fun cloneable(): <!UNRESOLVED_REFERENCE!>Cloneable<!> = intArrayOf(42)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun cloneable(): [ERROR : Cloneable]
|
||||||
+15
@@ -369,6 +369,21 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class JvmDeclarations extends AbstractDiagnosticsTestWithJsStdLib {
|
||||||
|
public void testAllFilesPresentInJvmDeclarations() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("cloneable.kt")
|
||||||
|
public void testCloneable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/jvmDeclarations/cloneable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module")
|
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+5
-2
@@ -27,11 +27,14 @@ import org.jetbrains.kotlin.storage.getValue
|
|||||||
|
|
||||||
class JvmBuiltInClassDescriptorFactory(
|
class JvmBuiltInClassDescriptorFactory(
|
||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
private val moduleDescriptor: ModuleDescriptor
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
|
private val computeContainingDeclaration: (ModuleDescriptor) -> DeclarationDescriptor = { module ->
|
||||||
|
module.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance<BuiltInsPackageFragment>().first()
|
||||||
|
}
|
||||||
) : ClassDescriptorFactory {
|
) : ClassDescriptorFactory {
|
||||||
private val cloneable by storageManager.createLazyValue {
|
private val cloneable by storageManager.createLazyValue {
|
||||||
ClassDescriptorImpl(
|
ClassDescriptorImpl(
|
||||||
moduleDescriptor.getPackage(KOTLIN_FQ_NAME).fragments.filterIsInstance<BuiltInsPackageFragment>().first(),
|
computeContainingDeclaration(moduleDescriptor),
|
||||||
CLONEABLE_NAME, Modality.ABSTRACT, ClassKind.INTERFACE, listOf(moduleDescriptor.builtIns.anyType),
|
CLONEABLE_NAME, Modality.ABSTRACT, ClassKind.INTERFACE, listOf(moduleDescriptor.builtIns.anyType),
|
||||||
SourceElement.NO_SOURCE, /* isExternal = */ false
|
SourceElement.NO_SOURCE, /* isExternal = */ false
|
||||||
).apply {
|
).apply {
|
||||||
|
|||||||
+5
-4
@@ -38,9 +38,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.AdditionalClassPartsProvider
|
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.PlatformDependentDeclarationFilter
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
@@ -66,7 +64,10 @@ open class JvmBuiltInsSettings(
|
|||||||
|
|
||||||
private val mockSerializableType = storageManager.createMockJavaIoSerializableType()
|
private val mockSerializableType = storageManager.createMockJavaIoSerializableType()
|
||||||
private val cloneableType by storageManager.createLazyValue {
|
private val cloneableType by storageManager.createLazyValue {
|
||||||
moduleDescriptor.builtIns.getBuiltInClassByName(JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID.shortClassName).defaultType
|
ownerModuleDescriptor.findNonGenericClassAcrossDependencies(
|
||||||
|
JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID,
|
||||||
|
NotFoundClasses(storageManager, ownerModuleDescriptor)
|
||||||
|
).defaultType
|
||||||
}
|
}
|
||||||
|
|
||||||
private val javaAnalogueClassesWithCustomSupertypeCache = storageManager.createCacheWithNotNullValues<FqName, ClassDescriptor>()
|
private val javaAnalogueClassesWithCustomSupertypeCache = storageManager.createCacheWithNotNullValues<FqName, ClassDescriptor>()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.builtins
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.ClassDeserializer
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
@@ -53,6 +54,8 @@ class BuiltInsPackageFragment(
|
|||||||
override fun computeMemberScope() =
|
override fun computeMemberScope() =
|
||||||
DeserializedPackageMemberScope(
|
DeserializedPackageMemberScope(
|
||||||
this, proto.`package`, nameResolver, containerSource = null, components = components,
|
this, proto.`package`, nameResolver, containerSource = null, components = components,
|
||||||
classNames = { classDataFinder.allClassIds.filter { classId -> !classId.isNestedClass }.map { it.shortClassName } }
|
classNames = { classDataFinder.allClassIds.filter { classId ->
|
||||||
|
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
|
||||||
|
}.map { it.shortClassName } }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.serialization.deserialization
|
package org.jetbrains.kotlin.serialization.deserialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.serialization.ClassDataWithSource
|
import org.jetbrains.kotlin.serialization.ClassDataWithSource
|
||||||
@@ -36,6 +37,8 @@ class ClassDeserializer(private val components: DeserializationComponents) {
|
|||||||
for (factory in components.fictitiousClassDescriptorFactories) {
|
for (factory in components.fictitiousClassDescriptorFactories) {
|
||||||
factory.createClass(classId)?.let { return it }
|
factory.createClass(classId)?.let { return it }
|
||||||
}
|
}
|
||||||
|
if (classId in BLACK_LIST) return null
|
||||||
|
|
||||||
val (classData, sourceElement) = key.classDataWithSource
|
val (classData, sourceElement) = key.classDataWithSource
|
||||||
?: components.classDataFinder.findClassData(classId)
|
?: components.classDataFinder.findClassData(classId)
|
||||||
?: return null
|
?: return null
|
||||||
@@ -76,4 +79,16 @@ class ClassDeserializer(private val components: DeserializationComponents) {
|
|||||||
|
|
||||||
override fun hashCode() = classId.hashCode()
|
override fun hashCode() = classId.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* FQ names of classes that should be ignored during deserialization.
|
||||||
|
*
|
||||||
|
* We ignore kotlin.Cloneable because since Kotlin 1.1, the descriptor for it is created via JvmBuiltInClassDescriptorFactory,
|
||||||
|
* but the metadata is still serialized for kotlin-reflect 1.0 to work (see BuiltInsSerializer.kt).
|
||||||
|
*/
|
||||||
|
val BLACK_LIST = setOf(
|
||||||
|
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe())
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user