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:
+7
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user