Fix exception in ultra-light classes in case of complex mpp hierarchy

Without the introduced override, default implementation of isEquivalentTo
runs delegate computation of `another` that is illegal
for KtUltraLightClass

^KT-28912 Fixed
This commit is contained in:
Denis Zharkov
2018-12-19 14:16:01 +03:00
parent be881442da
commit 2b40ecfd29
5 changed files with 39 additions and 2 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.caches.lightClasses
import com.intellij.ide.highlighter.JavaFileType import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.impl.light.AbstractLightClass import com.intellij.psi.impl.light.AbstractLightClass
import com.intellij.psi.impl.light.LightMethod import com.intellij.psi.impl.light.LightMethod
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
@@ -68,6 +69,8 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
else else
DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor) DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
} }
override fun isEquivalentTo(another: PsiElement?): Boolean = PsiClassImplUtil.isClassEquivalentTo(this, another)
} }
class KtFakeLightMethod private constructor( class KtFakeLightMethod private constructor(
@@ -0,0 +1,14 @@
// ULTRA_LIGHT_CLASSES
package test
expect interface Closable {
fun <caret>close()
}
expect class MyStream : Closable {}
open class MyImpl : Closable {
override fun close() {}
}
// REF: [testModule_Common] (in test.MyImpl).close()
@@ -0,0 +1,9 @@
package test
actual interface Closable {
fun close()
}
actual typealias MyStream = MyImpl
fun foo(): Any? = object : MyStream() {}
@@ -13,10 +13,12 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.codeInsight.GotoSuperActionHandler import org.jetbrains.kotlin.idea.codeInsight.GotoSuperActionHandler
import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure
import org.jetbrains.kotlin.idea.perf.forceUsingUltraLightClassesForTest
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.extractMarkerOffset import org.jetbrains.kotlin.idea.test.extractMarkerOffset
import org.jetbrains.kotlin.idea.test.findFileWithCaret import org.jetbrains.kotlin.idea.test.findFileWithCaret
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import java.io.File import java.io.File
abstract class AbstractKotlinNavigationMultiModuleTest : AbstractMultiModuleTest() { abstract class AbstractKotlinNavigationMultiModuleTest : AbstractMultiModuleTest() {
@@ -25,6 +27,10 @@ abstract class AbstractKotlinNavigationMultiModuleTest : AbstractMultiModuleTest
protected fun doTest(testDataDir: String) { protected fun doTest(testDataDir: String) {
setupMppProjectFromDirStructure(File(testDataDir)) setupMppProjectFromDirStructure(File(testDataDir))
val file = project.findFileWithCaret() val file = project.findFileWithCaret()
if (InTextDirectivesUtils.isDirectiveDefined(file.text, "ULTRA_LIGHT_CLASSES")) {
forceUsingUltraLightClassesForTest()
}
val doc = PsiDocumentManager.getInstance(myProject).getDocument(file)!! val doc = PsiDocumentManager.getInstance(myProject).getDocument(file)!!
val offset = doc.extractMarkerOffset(project, "<caret>") val offset = doc.extractMarkerOffset(project, "<caret>")
val editor = EditorFactory.getInstance().createEditor(doc, myProject) val editor = EditorFactory.getInstance().createEditor(doc, myProject)
@@ -25,6 +25,11 @@ public class KotlinGotoImplementationMultiModuleTestGenerated extends AbstractKo
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
} }
@TestMetadata("actualTypeAliasWithAnonymousSubclass")
public void testActualTypeAliasWithAnonymousSubclass() throws Exception {
runTest("idea/testData/navigation/implementations/multiModule/actualTypeAliasWithAnonymousSubclass/");
}
public void testAllFilesPresentInMultiModule() throws Exception { public void testAllFilesPresentInMultiModule() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/implementations/multiModule"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, false); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/implementations/multiModule"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, false);
} }