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