Do not load implClassName JVM proto extension

Use JvmPackagePartSource instead for functions/properties in package parts,
check containing class kind for properties in interfaces
This commit is contained in:
Alexander Udalov
2015-12-19 03:54:25 +03:00
parent 03606c13aa
commit cd435c4130
6 changed files with 54 additions and 78 deletions
@@ -21,12 +21,11 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.types.KotlinType
fun copyValueParameters(
@@ -34,7 +33,7 @@ fun copyValueParameters(
oldValueParameters: Collection<ValueParameterDescriptor>,
newOwner: CallableDescriptor
): List<ValueParameterDescriptor> {
assert(newValueParametersTypes.size() == oldValueParameters.size()) {
assert(newValueParametersTypes.size == oldValueParameters.size) {
"Different value parameters sizes: Enhanced = ${newValueParametersTypes.size}, Old = ${oldValueParameters.size}"
}
@@ -45,14 +44,14 @@ fun copyValueParameters(
newOwner,
oldParameter,
oldParameter.index,
oldParameter.getAnnotations(),
oldParameter.getName(),
oldParameter.annotations,
oldParameter.name,
newType,
oldParameter.declaresDefaultValue(),
oldParameter.isCrossinline,
oldParameter.isNoinline,
if (oldParameter.varargElementType != null) newOwner.module.builtIns.getArrayElementType(newType) else null,
oldParameter.getSource()
oldParameter.source
)
}
}
@@ -68,19 +67,5 @@ fun ClassDescriptor.getParentJavaStaticClassScope(): LazyJavaStaticClassScope? {
}
fun DeserializedCallableMemberDescriptor.getImplClassNameForDeserialized(): Name? {
val proto = proto
return when (proto) {
is ProtoBuf.Constructor ->
null
is ProtoBuf.Function ->
if (proto.hasExtension(JvmProtoBuf.methodImplClassName))
proto.getExtension(JvmProtoBuf.methodImplClassName)
else null
is ProtoBuf.Property ->
if (proto.hasExtension(JvmProtoBuf.propertyImplClassName))
proto.getExtension(JvmProtoBuf.propertyImplClassName)
else null
else ->
error("Unknown message: $proto")
}?.let { nameResolver.getName(it) }
return (packagePartSource as? JvmPackagePartSource)?.className?.fqNameForClassNameWithoutDollars?.shortName()
}
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.jvm.ClassMapperLite
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.*
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.index
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.propertySignature
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
@@ -95,26 +95,26 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
val fieldSignature = getPropertySignature(proto, container.nameResolver, container.typeTable, field = true)
val propertyAnnotations = syntheticFunctionSignature?.let { sig ->
findClassAndLoadMemberAnnotations(container, proto, sig)
findClassAndLoadMemberAnnotations(container, sig, property = true)
}.orEmpty()
val fieldAnnotations = fieldSignature?.let { sig ->
findClassAndLoadMemberAnnotations(container, proto, sig, field = true)
findClassAndLoadMemberAnnotations(container, sig, property = true, field = true)
}.orEmpty()
return loadPropertyAnnotations(propertyAnnotations, fieldAnnotations)
}
val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, kind) ?: return emptyList()
return transformAnnotations(findClassAndLoadMemberAnnotations(container, proto, signature))
return transformAnnotations(findClassAndLoadMemberAnnotations(container, signature))
}
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<A> {
val signature = MemberSignature.fromFieldNameAndDesc(
container.nameResolver.getString(proto.name),
ClassMapperLite.mapClass(container.nameResolver.getClassId((container as ProtoContainer.Class).classProto.fqName))
ClassMapperLite.mapClass((container as ProtoContainer.Class).classId)
)
return findClassAndLoadMemberAnnotations(container, proto, signature)
return findClassAndLoadMemberAnnotations(container, signature)
}
protected abstract fun loadPropertyAnnotations(propertyAnnotations: List<A>, fieldAnnotations: List<A>): List<T>
@@ -122,13 +122,10 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
protected abstract fun transformAnnotations(annotations: List<A>): List<T>
private fun findClassAndLoadMemberAnnotations(
container: ProtoContainer, proto: MessageLite, signature: MemberSignature, field: Boolean = false
container: ProtoContainer, signature: MemberSignature, property: Boolean = false, field: Boolean = false
): List<A> {
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(proto, container.nameResolver), field)
if (kotlinClass == null) {
errorReporter.reportLoadingError("Kotlin class for loading member annotations is not found: ${container.debugFqName()}", null)
return listOf()
}
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property), field)
?: return listOf()
return storage(kotlinClass).memberAnnotations[signature] ?: listOf()
}
@@ -144,7 +141,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
if (methodSignature != null) {
val index = if (proto.hasExtension(index)) proto.getExtension(index) else parameterIndex
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, index)
return findClassAndLoadMemberAnnotations(container, message, paramSignature)
return findClassAndLoadMemberAnnotations(container, paramSignature)
}
return listOf()
@@ -158,7 +155,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
val methodSignature = getCallableSignature(message, container.nameResolver, container.typeTable, kind)
if (methodSignature != null) {
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, 0)
return findClassAndLoadMemberAnnotations(container, message, paramSignature)
return findClassAndLoadMemberAnnotations(container, paramSignature)
}
return emptyList()
@@ -173,54 +170,41 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
}
override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): C? {
val nameResolver = container.nameResolver
val signature = getCallableSignature(proto, nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY) ?: return null
val signature = getCallableSignature(proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY)
?: return null
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(proto, nameResolver), field = true)
if (kotlinClass == null) {
errorReporter.reportLoadingError("Kotlin class for loading property constant is not found: ${container.debugFqName()}", null)
return null
}
val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(container, property = true), field = true)
?: return null
return storage(kotlinClass).propertyConstants[signature]
}
private fun findClassWithAnnotationsAndInitializers(
container: ProtoContainer, implClassName: Name?, field: Boolean
): KotlinJvmBinaryClass? = when (container) {
is ProtoContainer.Package -> {
implClassName?.let { kotlinClassFinder.findKotlinClass(ClassId(container.fqName, it)) }
container: ProtoContainer, implClassName: ClassId?, field: Boolean
): KotlinJvmBinaryClass? {
if (implClassName != null) {
return kotlinClassFinder.findKotlinClass(implClassName)
}
is ProtoContainer.Class -> {
val classId = container.nameResolver.getClassId(container.classProto.fqName)
if (implClassName != null) {
// TODO: store accurate name for nested traits
val implClassId =
if (implClassName.asString().endsWith(JvmAbi.DEFAULT_IMPLS_SUFFIX))
ClassId(classId.packageFqName, FqName(implClassName.asString().replace(JvmAbi.DEFAULT_IMPLS_SUFFIX, "." + JvmAbi.DEFAULT_IMPLS_CLASS_NAME)), false)
else
ClassId(classId.packageFqName, implClassName)
kotlinClassFinder.findKotlinClass(implClassId)
}
else if (field && container.isCompanionOfClass) {
if (container is ProtoContainer.Class) {
if (field && container.isCompanionOfClass) {
// Backing fields of properties of a companion object in a class are generated in the outer class
kotlinClassFinder.findKotlinClass(classId.outerClassId)
}
else {
kotlinClassFinder.findKotlinClass(classId)
return kotlinClassFinder.findKotlinClass(container.classId.outerClassId)
}
return kotlinClassFinder.findKotlinClass(container.classId)
}
return null
}
private fun getImplClassName(proto: MessageLite, nameResolver: NameResolver): Name? =
when {
proto is ProtoBuf.Function && proto.hasExtension(methodImplClassName) ->
nameResolver.getName(proto.getExtension(methodImplClassName))
proto is ProtoBuf.Property && proto.hasExtension(propertyImplClassName) ->
nameResolver.getName(proto.getExtension(propertyImplClassName))
else -> null
}
private fun getImplClassName(container: ProtoContainer, property: Boolean): ClassId? {
if (property && container is ProtoContainer.Class && container.isInterface) {
return container.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
}
return ((container as? ProtoContainer.Package)?.packagePartSource as? JvmPackagePartSource)
?.className?.fqNameForClassNameWithoutDollars?.let { ClassId.topLevel(it) }
}
private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage<A, C> {
val memberAnnotations = HashMap<MemberSignature, MutableList<A>>()
@@ -248,7 +248,8 @@ public class MemberDeserializer(private val c: DeserializationContext) {
is DeserializedClassDescriptor -> ProtoContainer.Class(
classProto, c.nameResolver, c.typeTable,
isCompanionOfClass = DescriptorUtils.isCompanionObject(this) &&
containingDeclaration.let { DescriptorUtils.isClass(it) || DescriptorUtils.isEnumClass(it) }
containingDeclaration.let { DescriptorUtils.isClass(it) || DescriptorUtils.isEnumClass(it) },
isInterface = kind == ClassKind.INTERFACE
)
else -> null // TODO: support annotations on lambdas and their parameters
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.serialization.deserialization
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.PackagePartSource
@@ -28,9 +29,12 @@ sealed class ProtoContainer(
val classProto: ProtoBuf.Class,
nameResolver: NameResolver,
typeTable: TypeTable,
val isCompanionOfClass: Boolean
val isCompanionOfClass: Boolean,
val isInterface: Boolean
) : ProtoContainer(nameResolver, typeTable) {
override fun debugFqName(): FqName = nameResolver.getClassId(classProto.fqName).asSingleFqName()
val classId: ClassId = nameResolver.getClassId(classProto.fqName)
override fun debugFqName(): FqName = classId.asSingleFqName()
}
class Package(
@@ -296,7 +296,8 @@ public class DeserializedClassDescriptor(
val annotations = enumEntryProtos[name]?.let { proto ->
DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadEnumEntryAnnotations(
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass = false), proto
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass = false, isInterface = false),
proto
)
}
} ?: if (name in oldEnumEntryNames) Annotations.EMPTY
@@ -68,6 +68,7 @@ private class ClassClsStubBuilder(
return classKind == ProtoBuf.Class.Kind.COMPANION_OBJECT &&
(outerContext.classKind?.let { it == ProtoBuf.Class.Kind.CLASS || it == ProtoBuf.Class.Kind.ENUM_CLASS } ?: false)
}
private val isInterface: Boolean get() = classKind == ProtoBuf.Class.Kind.INTERFACE
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
@@ -142,7 +143,7 @@ private class ClassClsStubBuilder(
val primaryConstructorProto = classProto.constructorList.find { !Flags.IS_SECONDARY.get(it.flags) } ?: return
createConstructorStub(classOrObjectStub, primaryConstructorProto, c,
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass))
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass, isInterface))
}
private fun createDelegationSpecifierList() {
@@ -180,7 +181,7 @@ private class ClassClsStubBuilder(
private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
if (classKind != ProtoBuf.Class.Kind.ENUM_CLASS) return
val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass = false)
val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass, isInterface)
val enumEntries: List<Pair<Int, List<ClassId>>> =
if (classProto.enumEntryList.isNotEmpty())
classProto.enumEntryList.map { enumEntryProto ->
@@ -211,7 +212,7 @@ private class ClassClsStubBuilder(
}
private fun createCallableMemberStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass)
val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass, isInterface)
for (secondaryConstructorProto in classProto.constructorList) {
if (Flags.IS_SECONDARY.get(secondaryConstructorProto.flags)) {