diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt index ae29b8ce415..f2e2c82a02a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt @@ -91,16 +91,15 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader findClassAndLoadMemberAnnotations(container, proto, sig) }.orEmpty() val fieldAnnotations = fieldSignature?.let { sig -> - findClassAndLoadMemberAnnotations(container, proto, sig, isStaticFieldInOuter(proto)) + findClassAndLoadMemberAnnotations(container, proto, sig, field = true) }.orEmpty() return loadPropertyAnnotations(propertyAnnotations, fieldAnnotations) @@ -123,14 +122,9 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader): List private fun findClassAndLoadMemberAnnotations( - container: ProtoContainer, - proto: MessageLite, - signature: MemberSignature, - isStaticFieldInOuter: Boolean = false + container: ProtoContainer, proto: MessageLite, signature: MemberSignature, field: Boolean = false ): List { - val kotlinClass = findClassWithAnnotationsAndInitializers( - container, getImplClassName(proto, container.nameResolver), isStaticFieldInOuter - ) + 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() @@ -182,9 +176,7 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader { implClassName?.let { kotlinClassFinder.findKotlinClass(ClassId(container.fqName, it)) } @@ -211,8 +203,8 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader 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 { val memberAnnotations = HashMap>() val propertyConstants = HashMap() diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt index 6edcb355bd6..6f43be3241c 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.resolve.DescriptorFactory +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.serialization.Flags import org.jetbrains.kotlin.serialization.ProtoBuf 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 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 } } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ProtoContainer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ProtoContainer.kt index c0947d1854c..10353e6d29c 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ProtoContainer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/ProtoContainer.kt @@ -26,7 +26,8 @@ sealed class ProtoContainer( class Class( val classProto: ProtoBuf.Class, nameResolver: NameResolver, - typeTable: TypeTable + typeTable: TypeTable, + val isCompanionOfClass: Boolean ) : ProtoContainer(nameResolver, typeTable) { override fun debugFqName(): FqName = nameResolver.getClassId(classProto.fqName).asSingleFqName() } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt index 8042e67bfb4..77b659b9a40 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt @@ -296,7 +296,7 @@ public class DeserializedClassDescriptor( val annotations = enumEntryProtos[name]?.let { proto -> DeserializedAnnotations(c.storageManager) { 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 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt index f0c5642f388..4c48a53dc90 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClassClsStubBuilder.kt @@ -50,9 +50,9 @@ private class ClassClsStubBuilder( private val classId: ClassId, 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 c = outerContext.child(classProto.typeParameterList, classKind, classId.shortClassName, TypeTable(classProto.typeTable)) + private val typeStubBuilder = TypeClsStubBuilder(c) private val supertypeIds = run { val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) } //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 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() @@ -137,7 +141,8 @@ 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)) + createConstructorStub(classOrObjectStub, primaryConstructorProto, c, + ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass)) } private fun createDelegationSpecifierList() { @@ -175,7 +180,7 @@ private class ClassClsStubBuilder( private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl) { 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>> = if (classProto.enumEntryList.isNotEmpty()) classProto.enumEntryList.map { enumEntryProto -> @@ -206,7 +211,7 @@ private class ClassClsStubBuilder( } private fun createCallableMemberStubs(classBody: KotlinPlaceHolderStubImpl) { - val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable) + val container = ProtoContainer.Class(classProto, c.nameResolver, c.typeTable, isCompanionOfClass) for (secondaryConstructorProto in classProto.constructorList) { if (Flags.IS_SECONDARY.get(secondaryConstructorProto.flags)) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt index 1ff45275054..72022f18a4e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt @@ -39,7 +39,7 @@ class ClsStubBuilderComponents( packageFqName: FqName, typeTable: TypeTable ): 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 containerFqName: FqName, val typeParameters: TypeParameters, - val typeTable: TypeTable + val typeTable: TypeTable, + val classKind: ProtoBuf.Class.Kind? ) internal fun ClsStubBuilderContext.child( typeParameterList: List, + classKind: ProtoBuf.Class.Kind? = null, name: Name? = null, typeTable: TypeTable = this.typeTable ): ClsStubBuilderContext { @@ -82,7 +84,8 @@ internal fun ClsStubBuilderContext.child( this.nameResolver, if (name != null) this.containerFqName.child(name) else this.containerFqName, this.typeParameters.child(nameResolver, typeParameterList), - typeTable + typeTable, + classKind ) } @@ -92,6 +95,7 @@ internal fun ClsStubBuilderContext.child(nameResolver: NameResolver, typeTable: nameResolver, this.containerFqName, this.typeParameters, - typeTable + typeTable, + classKind = null ) } diff --git a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt index cae3f43fee6..51fce783b2f 100644 --- a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt +++ b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt @@ -17,7 +17,7 @@ private @b(E.E2) companion object { - + @f val field = 42 } 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) annotation class c +@Target(AnnotationTarget.FIELD) +annotation class f + enum class E { E1, E2 } diff --git a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt index 8c99fd45505..1e8e65b3ee0 100644 --- a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt +++ b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt @@ -44,6 +44,19 @@ PsiJetFileStubImpl[package=] OBJECT_DECLARATION:[fqName=Annotations.Companion, isCompanion=true, isLocal=false, isObjectLiteral=false, isTopLevel=false, name=Companion, superNames=[]] MODIFIER_LIST:[private companion] 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] MODIFIER_LIST:[private final] TYPE_REFERENCE: