Do not use dummy resolving for light data classes which extend other classes

When using dummy resolving for creating stubs of data classes we do not have overriding information
which is needed to determine whether we need to generate synthetic members or not.
As a result of that, we may have two different versions of member scope: the first one is
resolved by dummy resolving and the second one resolved via an ordinary one.

As light methods depend on the index of them in the class body,
we can have two different methods with the same index
which breaks mapping from dummy resolved methods to normal ones.

This behaviour can be reproduced when having data class which
extends other class with some synthetic members overridden and marked as final
like described in #KT-32969

#KT-32969 fixed
This commit is contained in:
Ilya Kirillov
2019-08-05 18:20:14 +03:00
parent 39e15782b2
commit 5151659006
2 changed files with 29 additions and 0 deletions
@@ -187,6 +187,8 @@ internal object IDELightClassContexts {
if (isDataClassWithGeneratedMembersOverridden(classOrObject)) return false
if (isDataClassWhichExtendsOtherClass(classOrObject)) return false
if (hasMembersOverridingInternalMembers(classOrObject)) return false
if (hasSerializationLikeAnnotations(classOrObject)) return false
@@ -232,6 +234,11 @@ internal object IDELightClassContexts {
DataClassDescriptorResolver.isComponentLike(name)
}
private fun isDataClassWhichExtendsOtherClass(classOrObject: KtClassOrObject): Boolean {
return classOrObject.hasModifier(KtTokens.DATA_KEYWORD) &&
classOrObject.superTypeListEntries.isNotEmpty()
}
private fun hasMembersOverridingInternalMembers(classOrObject: KtClassOrObject): Boolean {
return classOrObject.declarations.filterIsInstance<KtCallableDeclaration>().any {
possiblyOverridesInternalMember(it)
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiType
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
@@ -104,6 +105,27 @@ class LightClassFromTextTest : KotlinLightCodeInsightFixtureTestCase() {
assertEquals(exampleClass, (f.returnType as PsiClassType).resolve())
}
// KT-32969
fun testDataClassWhichExtendsAbstractWithFinalToString() {
myFixture.configureByText(
"A.kt",
"""
abstract class A {
final override fun toString() = "nya"
}
""".trimIndent()
) as KtFile
val dataClass = classesFromText("data class D(val x: Int): A()").single()
for (method in dataClass.methods) {
if (method is KtLightMethod) {
// LazyLightClassMemberMatchingError$WrongMatch will be thrown
// if memberIndex conflict will be found
method.clsDelegate
}
}
}
fun testHeaderDeclarations() {
val contextFile = myFixture.configureByText("Header.kt", "header class Foo\n\nheader fun foo()\n") as KtFile
val headerClass = contextFile.declarations.single { it is KtClassOrObject }