Don't read isStaticInOuter message for fields

It's only written for fields of properties of companion objects of classes;
handle that case manually in deserialization
This commit is contained in:
Alexander Udalov
2015-12-17 03:50:37 +03:00
parent 696dce68fb
commit f7969621d6
8 changed files with 54 additions and 36 deletions
@@ -91,16 +91,15 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
if (kind == AnnotatedCallableKind.PROPERTY) { if (kind == AnnotatedCallableKind.PROPERTY) {
proto as ProtoBuf.Property proto as ProtoBuf.Property
val nameResolver = container.nameResolver val syntheticFunctionSignature = getPropertySignature(proto, container.nameResolver, container.typeTable, synthetic = true)
val syntheticFunctionSignature = getPropertySignature(proto, nameResolver, container.typeTable, synthetic = true) val fieldSignature = getPropertySignature(proto, container.nameResolver, container.typeTable, field = true)
val fieldSignature = getPropertySignature(proto, nameResolver, container.typeTable, field = true)
val propertyAnnotations = syntheticFunctionSignature?.let { sig -> val propertyAnnotations = syntheticFunctionSignature?.let { sig ->
findClassAndLoadMemberAnnotations(container, proto, sig) findClassAndLoadMemberAnnotations(container, proto, sig)
}.orEmpty() }.orEmpty()
val fieldAnnotations = fieldSignature?.let { sig -> val fieldAnnotations = fieldSignature?.let { sig ->
findClassAndLoadMemberAnnotations(container, proto, sig, isStaticFieldInOuter(proto)) findClassAndLoadMemberAnnotations(container, proto, sig, field = true)
}.orEmpty() }.orEmpty()
return loadPropertyAnnotations(propertyAnnotations, fieldAnnotations) return loadPropertyAnnotations(propertyAnnotations, fieldAnnotations)
@@ -123,14 +122,9 @@ 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, container: ProtoContainer, proto: MessageLite, signature: MemberSignature, field: Boolean = false
proto: MessageLite,
signature: MemberSignature,
isStaticFieldInOuter: Boolean = false
): List<A> { ): List<A> {
val kotlinClass = findClassWithAnnotationsAndInitializers( val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(proto, container.nameResolver), field)
container, getImplClassName(proto, container.nameResolver), isStaticFieldInOuter
)
if (kotlinClass == null) { if (kotlinClass == null) {
errorReporter.reportLoadingError("Kotlin class for loading member annotations is not found: ${container.debugFqName()}", null) errorReporter.reportLoadingError("Kotlin class for loading member annotations is not found: ${container.debugFqName()}", null)
return listOf() return listOf()
@@ -182,9 +176,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
val nameResolver = container.nameResolver val nameResolver = container.nameResolver
val signature = getCallableSignature(proto, nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY) ?: return null val signature = getCallableSignature(proto, nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY) ?: return null
val kotlinClass = findClassWithAnnotationsAndInitializers( val kotlinClass = findClassWithAnnotationsAndInitializers(container, getImplClassName(proto, nameResolver), field = true)
container, getImplClassName(proto, nameResolver), isStaticFieldInOuter(proto)
)
if (kotlinClass == null) { if (kotlinClass == null) {
errorReporter.reportLoadingError("Kotlin class for loading property constant is not found: ${container.debugFqName()}", null) errorReporter.reportLoadingError("Kotlin class for loading property constant is not found: ${container.debugFqName()}", null)
return null return null
@@ -194,7 +186,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
} }
private fun findClassWithAnnotationsAndInitializers( private fun findClassWithAnnotationsAndInitializers(
container: ProtoContainer, implClassName: Name?, isStaticFieldInOuter: Boolean container: ProtoContainer, implClassName: Name?, field: Boolean
): KotlinJvmBinaryClass? = when (container) { ): KotlinJvmBinaryClass? = when (container) {
is ProtoContainer.Package -> { is ProtoContainer.Package -> {
implClassName?.let { kotlinClassFinder.findKotlinClass(ClassId(container.fqName, it)) } implClassName?.let { kotlinClassFinder.findKotlinClass(ClassId(container.fqName, it)) }
@@ -211,8 +203,8 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
ClassId(classId.packageFqName, implClassName) ClassId(classId.packageFqName, implClassName)
kotlinClassFinder.findKotlinClass(implClassId) kotlinClassFinder.findKotlinClass(implClassId)
} }
else if (isStaticFieldInOuter && classId.isNestedClass) { else if (field && container.isCompanionOfClass) {
// Backing fields of properties of a companion object 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) kotlinClassFinder.findKotlinClass(classId.outerClassId)
} }
else { else {
@@ -230,11 +222,6 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C
else -> null else -> null
} }
private fun isStaticFieldInOuter(proto: MessageLite): Boolean =
if (proto is ProtoBuf.Property && proto.hasExtension(propertySignature))
proto.getExtension(propertySignature).let { it.hasField() && it.field.isStaticInOuter }
else false
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>>()
val propertyConstants = HashMap<MemberSignature, C>() val propertyConstants = HashMap<MemberSignature, C>()
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.Flags import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
@@ -241,9 +242,13 @@ public class MemberDeserializer(private val c: DeserializationContext) {
} }
} }
private fun DeclarationDescriptor.asProtoContainer(): ProtoContainer? = when(this) { private fun DeclarationDescriptor.asProtoContainer(): ProtoContainer? = when (this) {
is PackageFragmentDescriptor -> ProtoContainer.Package(fqName, c.nameResolver, c.typeTable) is PackageFragmentDescriptor -> ProtoContainer.Package(fqName, c.nameResolver, c.typeTable)
is DeserializedClassDescriptor -> ProtoContainer.Class(classProto, c.nameResolver, c.typeTable) is DeserializedClassDescriptor -> ProtoContainer.Class(
classProto, c.nameResolver, c.typeTable,
isCompanionOfClass = DescriptorUtils.isCompanionObject(this) &&
containingDeclaration.let { DescriptorUtils.isClass(it) || DescriptorUtils.isEnumClass(it) }
)
else -> null // TODO: support annotations on lambdas and their parameters else -> null // TODO: support annotations on lambdas and their parameters
} }
} }
@@ -26,7 +26,8 @@ sealed class ProtoContainer(
class Class( class Class(
val classProto: ProtoBuf.Class, val classProto: ProtoBuf.Class,
nameResolver: NameResolver, nameResolver: NameResolver,
typeTable: TypeTable typeTable: TypeTable,
val isCompanionOfClass: Boolean
) : ProtoContainer(nameResolver, typeTable) { ) : ProtoContainer(nameResolver, typeTable) {
override fun debugFqName(): FqName = nameResolver.getClassId(classProto.fqName).asSingleFqName() override fun debugFqName(): FqName = nameResolver.getClassId(classProto.fqName).asSingleFqName()
} }
@@ -296,7 +296,7 @@ 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), proto ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass = false), proto
) )
} }
} ?: if (name in oldEnumEntryNames) Annotations.EMPTY } ?: if (name in oldEnumEntryNames) Annotations.EMPTY
@@ -50,9 +50,9 @@ private class ClassClsStubBuilder(
private val classId: ClassId, private val classId: ClassId,
private val outerContext: ClsStubBuilderContext private val outerContext: ClsStubBuilderContext
) { ) {
private val c = outerContext.child(classProto.typeParameterList, classId.shortClassName, TypeTable(classProto.typeTable))
private val typeStubBuilder = TypeClsStubBuilder(c)
private val classKind = Flags.CLASS_KIND[classProto.flags] private val classKind = Flags.CLASS_KIND[classProto.flags]
private val c = outerContext.child(classProto.typeParameterList, classKind, classId.shortClassName, TypeTable(classProto.typeTable))
private val typeStubBuilder = TypeClsStubBuilder(c)
private val supertypeIds = run { private val supertypeIds = run {
val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) } val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) }
//empty supertype list if single supertype is Any //empty supertype list if single supertype is Any
@@ -64,6 +64,10 @@ private class ClassClsStubBuilder(
} }
} }
private val companionObjectName = if (classProto.hasCompanionObjectName()) c.nameResolver.getName(classProto.getCompanionObjectName()) else null private val companionObjectName = if (classProto.hasCompanionObjectName()) c.nameResolver.getName(classProto.getCompanionObjectName()) else null
private val isCompanionOfClass: Boolean get() {
return classKind == ProtoBuf.Class.Kind.COMPANION_OBJECT &&
(outerContext.classKind?.let { it == ProtoBuf.Class.Kind.CLASS || it == ProtoBuf.Class.Kind.ENUM_CLASS } ?: false)
}
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub() private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
@@ -137,7 +141,8 @@ 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, ProtoContainer.Class(classProto, c.nameResolver, c.typeTable)) createConstructorStub(classOrObjectStub, primaryConstructorProto, c,
ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass))
} }
private fun createDelegationSpecifierList() { private fun createDelegationSpecifierList() {
@@ -175,7 +180,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) val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass = false)
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 ->
@@ -206,7 +211,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) val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass)
for (secondaryConstructorProto in classProto.constructorList) { for (secondaryConstructorProto in classProto.constructorList) {
if (Flags.IS_SECONDARY.get(secondaryConstructorProto.flags)) { if (Flags.IS_SECONDARY.get(secondaryConstructorProto.flags)) {
@@ -39,7 +39,7 @@ class ClsStubBuilderComponents(
packageFqName: FqName, packageFqName: FqName,
typeTable: TypeTable typeTable: TypeTable
): ClsStubBuilderContext { ): ClsStubBuilderContext {
return ClsStubBuilderContext(this, nameResolver, packageFqName, EmptyTypeParameters, typeTable) return ClsStubBuilderContext(this, nameResolver, packageFqName, EmptyTypeParameters, typeTable, classKind = null)
} }
} }
@@ -69,11 +69,13 @@ class ClsStubBuilderContext(
val nameResolver: NameResolver, val nameResolver: NameResolver,
val containerFqName: FqName, val containerFqName: FqName,
val typeParameters: TypeParameters, val typeParameters: TypeParameters,
val typeTable: TypeTable val typeTable: TypeTable,
val classKind: ProtoBuf.Class.Kind?
) )
internal fun ClsStubBuilderContext.child( internal fun ClsStubBuilderContext.child(
typeParameterList: List<ProtoBuf.TypeParameter>, typeParameterList: List<ProtoBuf.TypeParameter>,
classKind: ProtoBuf.Class.Kind? = null,
name: Name? = null, name: Name? = null,
typeTable: TypeTable = this.typeTable typeTable: TypeTable = this.typeTable
): ClsStubBuilderContext { ): ClsStubBuilderContext {
@@ -82,7 +84,8 @@ internal fun ClsStubBuilderContext.child(
this.nameResolver, this.nameResolver,
if (name != null) this.containerFqName.child(name) else this.containerFqName, if (name != null) this.containerFqName.child(name) else this.containerFqName,
this.typeParameters.child(nameResolver, typeParameterList), this.typeParameters.child(nameResolver, typeParameterList),
typeTable typeTable,
classKind
) )
} }
@@ -92,6 +95,7 @@ internal fun ClsStubBuilderContext.child(nameResolver: NameResolver, typeTable:
nameResolver, nameResolver,
this.containerFqName, this.containerFqName,
this.typeParameters, this.typeParameters,
typeTable typeTable,
classKind = null
) )
} }
@@ -17,7 +17,7 @@
private @b(E.E2) companion object { private @b(E.E2) companion object {
@f val field = 42
} }
class Nested @a private @b(E.E1) @b(E.E2) constructor() class Nested @a private @b(E.E1) @b(E.E2) constructor()
@@ -43,4 +43,7 @@ annotation class b(val e: E)
AnnotationTarget.TYPE, AnnotationTarget.CLASS) AnnotationTarget.TYPE, AnnotationTarget.CLASS)
annotation class c annotation class c
@Target(AnnotationTarget.FIELD)
annotation class f
enum class E { E1, E2 } enum class E { E1, E2 }
@@ -44,6 +44,19 @@ PsiJetFileStubImpl[package=]
OBJECT_DECLARATION:[fqName=Annotations.Companion, isCompanion=true, isLocal=false, isObjectLiteral=false, isTopLevel=false, name=Companion, superNames=[]] OBJECT_DECLARATION:[fqName=Annotations.Companion, isCompanion=true, isLocal=false, isObjectLiteral=false, isTopLevel=false, name=Companion, superNames=[]]
MODIFIER_LIST:[private companion] MODIFIER_LIST:[private companion]
CLASS_BODY: CLASS_BODY:
PROPERTY:[fqName=Annotations.Companion.field, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=field]
MODIFIER_LIST:[public final]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=f]
ANNOTATION_TARGET:[useSiteTarget=FIELD]
CONSTRUCTOR_CALLEE:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=f]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
PROPERTY:[fqName=Annotations.c, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=c] PROPERTY:[fqName=Annotations.c, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=c]
MODIFIER_LIST:[private final] MODIFIER_LIST:[private final]
TYPE_REFERENCE: TYPE_REFERENCE: