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.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.impl.light.AbstractLightClass
import com.intellij.psi.impl.light.LightMethod
import com.intellij.util.IncorrectOperationException
@@ -68,6 +69,8 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
else
DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
}
override fun isEquivalentTo(another: PsiElement?): Boolean = PsiClassImplUtil.isClassEquivalentTo(this, another)
}
class KtFakeLightMethod private constructor(
@@ -122,4 +125,4 @@ private object DummyJavaPsiFactory {
}
private val DUMMY_FILE_NAME = "_Dummy_." + JavaFileType.INSTANCE.defaultExtension
}
}
@@ -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 org.jetbrains.kotlin.idea.codeInsight.GotoSuperActionHandler
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.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.extractMarkerOffset
import org.jetbrains.kotlin.idea.test.findFileWithCaret
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import java.io.File
abstract class AbstractKotlinNavigationMultiModuleTest : AbstractMultiModuleTest() {
@@ -25,6 +27,10 @@ abstract class AbstractKotlinNavigationMultiModuleTest : AbstractMultiModuleTest
protected fun doTest(testDataDir: String) {
setupMppProjectFromDirStructure(File(testDataDir))
val file = project.findFileWithCaret()
if (InTextDirectivesUtils.isDirectiveDefined(file.text, "ULTRA_LIGHT_CLASSES")) {
forceUsingUltraLightClassesForTest()
}
val doc = PsiDocumentManager.getInstance(myProject).getDocument(file)!!
val offset = doc.extractMarkerOffset(project, "<caret>")
val editor = EditorFactory.getInstance().createEditor(doc, myProject)
@@ -65,4 +71,4 @@ abstract class AbstractKotlinGotoRelatedSymbolMultiModuleTest : AbstractKotlinNa
val relatedItems = NavigationUtil.collectRelatedItems(source, null)
return GotoTargetHandler.GotoData(source, relatedItems.map { it.element }.toTypedArray(), emptyList())
}
}
}
@@ -25,6 +25,11 @@ public class KotlinGotoImplementationMultiModuleTestGenerated extends AbstractKo
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 {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/implementations/multiModule"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, false);
}