kotlin.reflect.jvm.internal.impl.serialization.deserialization.NotFoundClasses.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 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.impl.serialization.deserialization
import kotlin.reflect.jvm.internal.impl.descriptors.*
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.Annotations
import kotlin.reflect.jvm.internal.impl.descriptors.impl.AbstractTypeAliasDescriptor
import kotlin.reflect.jvm.internal.impl.descriptors.impl.ClassDescriptorBase
import kotlin.reflect.jvm.internal.impl.descriptors.impl.EmptyPackageFragmentDescriptor
import kotlin.reflect.jvm.internal.impl.descriptors.impl.TypeParameterDescriptorImpl
import kotlin.reflect.jvm.internal.impl.name.ClassId
import kotlin.reflect.jvm.internal.impl.name.FqName
import kotlin.reflect.jvm.internal.impl.name.Name
import kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil.builtIns
import kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil.fqNameUnsafe
import kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil.module
import kotlin.reflect.jvm.internal.impl.resolve.scopes.MemberScope
import kotlin.reflect.jvm.internal.impl.serialization.ProtoBuf
import kotlin.reflect.jvm.internal.impl.storage.StorageManager
import kotlin.reflect.jvm.internal.impl.storage.getValue
import kotlin.reflect.jvm.internal.impl.types.*
class NotFoundClasses(private val storageManager: StorageManager, private val module: ModuleDescriptor) {
/**
* @param typeParametersCount list of numbers of type parameters in this class and all its outer classes, starting from this class
*/
private data class ClassRequest(val classId: ClassId, val typeParametersCount: List)
private val packageFragments = storageManager.createMemoizedFunction { fqName ->
EmptyPackageFragmentDescriptor(module, fqName)
}
private val classes = storageManager.createMemoizedFunction { request ->
computeClassifier(request, {
owner, name, isInner, numberOfTypeParametersCount ->
MockClassDescriptor(storageManager, owner, name, isInner, numberOfTypeParametersCount)
})
}
private val typeAliases = storageManager.createMemoizedFunction { request ->
computeClassifier(request, {
owner, name, isInner, numberOfTypeParametersCount ->
MockTypeAliasDescriptor(storageManager, owner, name, isInner, numberOfTypeParametersCount)
})
}
// TODO: Uncomment this when KT-12871 is fixed
// private typealias ConstructorFunction = (DeclarationDescriptor, Name, isInner: Boolean, numberOfTypeParametersCount: Int) -> D
private fun computeClassifier(
request: ClassRequest,
constructor: (DeclarationDescriptor, Name, isInner: Boolean, numberOfTypeParametersCount: Int) -> D
): D {
val (classId, typeParametersCount) = request
if (classId.isLocal) {
throw UnsupportedOperationException("Unresolved local class: $classId")
}
val container =
if (classId.isNestedClass) getOrCreateClass(classId.outerClassId, typeParametersCount.drop(1))
else packageFragments(classId.packageFqName)
// Treat a class with a nested ClassId as inner for simplicity, otherwise the outer type cannot have generic arguments
val isInner = classId.isNestedClass
return constructor(container, classId.shortClassName, isInner, typeParametersCount.firstOrNull() ?: 0)
}
class MockClassDescriptor internal constructor(
storageManager: StorageManager,
container: DeclarationDescriptor,
name: Name,
private val isInner: Boolean,
numberOfDeclaredTypeParameters: Int
) : ClassDescriptorBase(storageManager, container, name, SourceElement.NO_SOURCE, /* isExternal = */ false) {
private val typeParameters = createTypeParameters(this, numberOfDeclaredTypeParameters)
private val typeConstructor = ClassTypeConstructorImpl(this, /* isFinal = */ true, typeParameters, setOf(module.builtIns.anyType))
override fun getKind() = ClassKind.CLASS
override fun getModality() = Modality.FINAL
override fun getVisibility() = Visibilities.PUBLIC
override fun getTypeConstructor() = typeConstructor
override fun getDeclaredTypeParameters() = typeParameters
override fun isInner() = isInner
override fun isCompanionObject() = false
override fun isData() = false
override fun isHeader() = false
override fun isImpl() = false
override fun isExternal() = false
override val annotations: Annotations get() = Annotations.EMPTY
override fun getUnsubstitutedMemberScope() = MemberScope.Empty
override fun getStaticScope() = MemberScope.Empty
override fun getConstructors(): Collection = emptySet()
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
override fun getSealedSubclasses(): Collection = emptyList()
override fun toString() = "class $name (not found)"
}
private class MockTypeAliasDescriptor(
storageManager: StorageManager,
containingDeclaration: DeclarationDescriptor,
name: Name,
private val isInner: Boolean,
numberOfDeclaredTypeParameters: Int
) : AbstractTypeAliasDescriptor(containingDeclaration, Annotations.EMPTY, name, SourceElement.NO_SOURCE, Visibilities.PUBLIC) {
init {
initialize(createTypeParameters(this, numberOfDeclaredTypeParameters))
}
private val constructorTypeParameters by storageManager.createLazyValue { computeConstructorTypeParameters() }
override fun getTypeConstructorTypeParameters() = constructorTypeParameters
// We don't have enough information about underlying type, so just take nullable Any?
// Anyway it should not used extensively, because not found type aliases are only used for type abbreviations
override val underlyingType: SimpleType
get() = builtIns.nullableAnyType
override val expandedType: SimpleType
get() = builtIns.nullableAnyType
override fun getDefaultType(): SimpleType =
builtIns.nullableAnyType
override val classDescriptor: ClassDescriptor?
get() = expandedType.constructor.declarationDescriptor as? ClassDescriptor
override fun isInner(): Boolean = isInner
override fun substitute(substitutor: TypeSubstitutor) = this
override fun toString() = "MockTypeAliasDescriptor[$fqNameUnsafe]"
}
// We create different ClassDescriptor instances for types with the same ClassId but different number of type arguments.
// (This may happen when a class with the same FQ name is instantiated with different type arguments in different modules.)
// It's better than creating just one descriptor because otherwise would fail in multiple places where it's asserted that
// the number of type arguments in a type must be equal to the number of the type parameters of the class
private fun getOrCreateClass(classId: ClassId, typeParametersCount: List): ClassDescriptor {
return classes(ClassRequest(classId, typeParametersCount))
}
fun getClass(proto: ProtoBuf.Type, nameResolver: NameResolver, typeTable: TypeTable): TypeConstructor {
val classId = nameResolver.getClassId(proto.className)
return getOrCreateClass(classId, computeTypeParametersCount(classId, proto, typeTable)).typeConstructor
}
fun getClass(classId: ClassId, typeParametersCount: List): TypeConstructor {
return getOrCreateClass(classId, typeParametersCount).typeConstructor
}
fun getTypeAlias(proto: ProtoBuf.Type, nameResolver: NameResolver, typeTable: TypeTable): TypeConstructor {
val classId = nameResolver.getClassId(proto.typeAliasName)
return typeAliases(ClassRequest(classId, computeTypeParametersCount(classId, proto, typeTable))).typeConstructor
}
}
private fun createTypeParameters(
classifierDescriptor: ClassifierDescriptor,
numberOfDeclaredTypeParameters: Int
) = (1..numberOfDeclaredTypeParameters).map { index ->
TypeParameterDescriptorImpl.createWithDefaultBound(
classifierDescriptor, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T$index"), index
)
}
private fun computeTypeParametersCount(classId: ClassId, proto: ProtoBuf.Type, typeTable: TypeTable): List {
val typeParametersCount = generateSequence(proto) { it.outerType(typeTable) }.map { it.argumentCount }.toMutableList()
val classNestingLevel = generateSequence(classId) { if (it.isNestedClass) it.outerClassId else null }.count()
while (typeParametersCount.size < classNestingLevel) {
typeParametersCount.add(0)
}
return typeParametersCount
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy