diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt index c1b62b3104e..07f037345b3 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt @@ -28,6 +28,7 @@ object KotlinStubVersions { // Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed // or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder). // Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files). + // TODO: Before updating this, please see the kdoc at DeserializedMemberScope.computeDescriptors and KT-41859 private const val BINARY_STUB_VERSION = 71 // Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt index 275064758b2..ffa77b52a1e 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt @@ -99,13 +99,24 @@ abstract class DeserializedMemberScope protected constructor( return impl.getContributedVariables(name, location) } + /** + * N.B. Currently the order of declarations here and in the [MemberComparator] is intentionally different: + * [MemberComparator] places classes first and typealiases second. + * + * However, `ClassClsStubBuilder` places typealiases first and classes second. This leads to + * Stub vs Psi mismatch error, when we have a class which have both inner typealiases and inner classes. + * This is unintentional and should be fixed. + * + * We do not want to update stubs versions prematurely, so we temporary mitigate the issue by making sure that + * order in stubs (in `ClassClsStubBuilder`) and here (in [DeserializedMemberScope]) is the same. As soon as the + * opportunity to bump the stubs version arises, we should fix the bug in the `ClassClsStubBuilder`, and + * fix the order here accordingly. + */ protected fun computeDescriptors( kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, location: LookupLocation ): Collection { - //NOTE: descriptors should be in the same order they were serialized in - // see MemberComparator val result = ArrayList(0) if (kindFilter.acceptsKinds(DescriptorKindFilter.SINGLETON_CLASSIFIERS_MASK)) { @@ -114,14 +125,6 @@ abstract class DeserializedMemberScope protected constructor( impl.addFunctionsAndPropertiesTo(result, kindFilter, nameFilter, location) - if (kindFilter.acceptsKinds(DescriptorKindFilter.CLASSIFIERS_MASK)) { - for (className in classNames) { - if (nameFilter(className)) { - result.addIfNotNull(deserializeClass(className)) - } - } - } - if (kindFilter.acceptsKinds(DescriptorKindFilter.TYPE_ALIASES_MASK)) { for (typeAliasName in impl.typeAliasNames) { if (nameFilter(typeAliasName)) { @@ -130,6 +133,14 @@ abstract class DeserializedMemberScope protected constructor( } } + if (kindFilter.acceptsKinds(DescriptorKindFilter.CLASSIFIERS_MASK)) { + for (className in classNames) { + if (nameFilter(className)) { + result.addIfNotNull(deserializeClass(className)) + } + } + } + return result.compact() } 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 eb70c83ee5a..579d6968648 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 @@ -219,6 +219,7 @@ private class ClassClsStubBuilder( } } + // FIXME using this function breaks the order of `MemberComparator` (see KT-41859) createDeclarationsStubs( classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList, classProto.typeAliasList ) diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt index 5e0d879f2c1..3309a593352 100644 --- a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.kt @@ -15,6 +15,8 @@ annotation class Ann class TypeAliases { + class OrderB + @Suppress("TOPLEVEL_TYPEALIASES_ONLY") typealias B = (A) -> Unit @@ -28,6 +30,8 @@ class TypeAliases { fun order(path: String) {} fun order(body: Z) {} + + class OrderA } diff --git a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt index 1be32771b01..183342c3500 100644 --- a/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt +++ b/idea/testData/decompiler/stubBuilder/TypeAliases/TypeAliases.txt @@ -139,3 +139,15 @@ PsiJetFileStubImpl[package=test] TYPE_REFERENCE USER_TYPE REFERENCE_EXPRESSION[referencedName=F] + CLASS[fqName=test.TypeAliases.OrderA, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=OrderA, superNames=[]] + MODIFIER_LIST[public final] + PRIMARY_CONSTRUCTOR + MODIFIER_LIST[public] + VALUE_PARAMETER_LIST + CLASS_BODY + CLASS[fqName=test.TypeAliases.OrderB, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=OrderB, superNames=[]] + MODIFIER_LIST[public final] + PRIMARY_CONSTRUCTOR + MODIFIER_LIST[public] + VALUE_PARAMETER_LIST + CLASS_BODY