Navigation: add expect declarations as supers #KT-16892 Fixed

This commit is contained in:
Mikhail Glukhikh
2018-03-07 18:09:45 +03:00
parent 849f9fc5c1
commit ab30275f14
10 changed files with 99 additions and 14 deletions
@@ -214,7 +214,7 @@ fun main(args: Array<String>) {
} }
testClass<AbstractGotoSuperTest> { testClass<AbstractGotoSuperTest> {
model("navigation/gotoSuper", extension = "test") model("navigation/gotoSuper", extension = "test", recursive = false)
} }
testClass<AbstractGotoTypeDeclarationTest> { testClass<AbstractGotoTypeDeclarationTest> {
@@ -22,14 +22,14 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations import org.jetbrains.kotlin.idea.core.getDirectlyOverriddenDeclarations
import org.jetbrains.kotlin.idea.highlighter.markers.expectedDeclarationIfAny
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class GotoSuperActionHandler : CodeInsightActionHandler { class GotoSuperActionHandler : CodeInsightActionHandler {
override fun invoke(project: Project, editor: Editor, file: PsiFile) { internal fun allSuperDeclarationsAndDescriptor(editor: Editor, file: PsiFile): Pair<List<PsiElement>, DeclarationDescriptor?> {
FeatureUsageTracker.getInstance().triggerFeatureUsed(GotoSuperAction.FEATURE_ID) val element = file.findElementAt(editor.caretModel.offset) ?: return emptyList<PsiElement>() to null
val element = file.findElementAt(editor.caretModel.offset) ?: return
val declaration = val declaration =
PsiTreeUtil.getParentOfType<KtDeclaration>( PsiTreeUtil.getParentOfType<KtDeclaration>(
element, element,
@@ -37,21 +37,28 @@ class GotoSuperActionHandler : CodeInsightActionHandler {
KtClass::class.java, KtClass::class.java,
KtProperty::class.java, KtProperty::class.java,
KtObjectDeclaration::class.java KtObjectDeclaration::class.java
) ?: return ) ?: return emptyList<PsiElement>() to null
val expectDeclaration = if (declaration.hasActualModifier()) declaration.expectedDeclarationIfAny() else null
val descriptor = declaration.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) val descriptor = declaration.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL)
val superDeclarations = findSuperDeclarations(file.project, descriptor)
return ((superDeclarations ?: emptyList()) + listOfNotNull(expectDeclaration)) to descriptor
}
val superDeclarations = findSuperDeclarations(project, descriptor) override fun invoke(project: Project, editor: Editor, file: PsiFile) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(GotoSuperAction.FEATURE_ID)
if (superDeclarations == null || superDeclarations.isEmpty()) return val (allDeclarations, descriptor) = allSuperDeclarationsAndDescriptor(editor, file)
if (superDeclarations.size == 1) { if (allDeclarations.isEmpty()) return
val navigatable = EditSourceUtil.getDescriptor(superDeclarations[0]) if (allDeclarations.size == 1) {
val navigatable = EditSourceUtil.getDescriptor(allDeclarations[0])
if (navigatable != null && navigatable.canNavigate()) { if (navigatable != null && navigatable.canNavigate()) {
navigatable.navigate(true) navigatable.navigate(true)
} }
} else { } else {
val message = getTitle(descriptor) val message = getTitle(descriptor!!)
val superDeclarationsArray = PsiUtilCore.toPsiElementArray(superDeclarations) val superDeclarationsArray = PsiUtilCore.toPsiElementArray(allDeclarations)
val popup = if (descriptor is ClassDescriptor) val popup = if (descriptor is ClassDescriptor)
NavigationUtil.getPsiElementPopup(superDeclarationsArray, message) NavigationUtil.getPsiElementPopup(superDeclarationsArray, message)
else else
@@ -64,7 +71,7 @@ class GotoSuperActionHandler : CodeInsightActionHandler {
} }
private fun getTitle(descriptor: DeclarationDescriptor): String? = private fun getTitle(descriptor: DeclarationDescriptor): String? =
when(descriptor) { when (descriptor) {
is ClassDescriptor -> KotlinBundle.message("goto.super.class.chooser.title") is ClassDescriptor -> KotlinBundle.message("goto.super.class.chooser.title")
is PropertyDescriptor -> KotlinBundle.message("goto.super.property.chooser.title") is PropertyDescriptor -> KotlinBundle.message("goto.super.property.chooser.title")
is SimpleFunctionDescriptor -> KotlinBundle.message("goto.super.function.chooser.title") is SimpleFunctionDescriptor -> KotlinBundle.message("goto.super.function.chooser.title")
@@ -0,0 +1,3 @@
package test
expect class Expected
@@ -0,0 +1,5 @@
package test
actual class <caret>Expected
// REF: [common] (test).Expected
@@ -0,0 +1,7 @@
package test
expect class Expected {
fun foo(): Int
val bar: String
}
@@ -0,0 +1,10 @@
package test
actual class Expected {
actual fun <caret>foo() = 42
actual val bar = "Hello"
}
// REF: [common] (in test.Expected).foo()
@@ -0,0 +1,7 @@
package test
expect class Expected {
fun foo(): Int
val bar: String
}
@@ -0,0 +1,10 @@
package test
actual class Expected {
actual fun foo() = 42
actual val <caret>bar = "Hello"
}
// REF: [common] (in test.Expected).bar
@@ -22,7 +22,7 @@ import java.util.regex.Pattern;
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
public class GotoSuperTestGenerated extends AbstractGotoSuperTest { public class GotoSuperTestGenerated extends AbstractGotoSuperTest {
public void testAllFilesPresentInGotoSuper() throws Exception { public void testAllFilesPresentInGotoSuper() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/gotoSuper"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/navigation/gotoSuper"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY, false);
} }
@TestMetadata("BadPositionLambdaParameter.test") @TestMetadata("BadPositionLambdaParameter.test")
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.navigation
import com.intellij.codeInsight.navigation.GotoTargetHandler
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.codeInsight.GotoSuperActionHandler
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import java.io.File
class KotlinGotoSuperMultiModuleTest : AbstractKotlinNavigationMultiModuleTest() {
override fun doNavigate(editor: Editor, file: PsiFile): GotoTargetHandler.GotoData {
val gotoAction = GotoSuperActionHandler()
val (superDeclarations, _) = gotoAction.allSuperDeclarationsAndDescriptor(editor, file)
return GotoTargetHandler.GotoData(file.findElementAt(editor.caretModel.offset)!!, superDeclarations.toTypedArray(), emptyList())
}
override fun getTestDataPath() =
File(PluginTestCaseBase.getTestDataPathBase(), "/navigation/gotoSuper/multiModule").path + File.separator
fun testActualClass() {
doMultiPlatformTest("jvm.kt")
}
fun testActualFunction() {
doMultiPlatformTest("jvm.kt")
}
fun testActualProperty() {
doMultiPlatformTest("jvm.kt")
}
}