From d49e9d7064740ff0328432396b6b82bde38ccbdc Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 27 Apr 2017 15:49:25 +0200 Subject: [PATCH] Fix override navigation from properties defined in primary constructor EA-91185 - CCE: KotlinLineMarkerProviderKt$OVERRIDDEN_PROPERTY$.browse --- .../markers/KotlinLineMarkerProvider.kt | 37 ++++++++++++++++--- .../markers/OverridenFunctionMarker.kt | 23 ++++++------ .../markers/OverridenPropertyMarker.kt | 28 +++++++------- .../PrimaryConstructorOpen.kt | 7 ++++ .../codeInsight/AbstractLineMarkersTest.kt | 5 +-- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt index eb8005bb354..dd30cd763cf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.highlighter.markers import com.intellij.codeHighlighting.Pass +import com.intellij.codeInsight.daemon.GutterIconNavigationHandler import com.intellij.codeInsight.daemon.LineMarkerInfo import com.intellij.codeInsight.daemon.LineMarkerProvider import com.intellij.codeInsight.daemon.impl.LineMarkerNavigator @@ -132,23 +133,47 @@ private val SUBCLASSED_CLASS = MarkerType( } }) -private val OVERRIDDEN_FUNCTION = MarkerType( +private val OVERRIDDEN_FUNCTION = object : MarkerType( "OVERRIDDEN_FUNCTION", { getPsiMethod(it)?.let(::getOverriddenMethodTooltip) }, object : LineMarkerNavigator() { override fun browse(e: MouseEvent?, element: PsiElement?) { - getPsiMethod(element)?.let { navigateToOverriddenMethod(e, it) } + buildNavigateToOverriddenMethodPopup(e, element)?.showPopup(e) } - }) + }) { -private val OVERRIDDEN_PROPERTY = MarkerType( + override fun getNavigationHandler(): GutterIconNavigationHandler { + val superHandler = super.getNavigationHandler() + return object : GutterIconNavigationHandler, TestableLineMarkerNavigator { + override fun navigate(e: MouseEvent?, elt: PsiElement?) { + superHandler.navigate(e, elt) + } + + override fun getTargetsPopupDescriptor(element: PsiElement?) = buildNavigateToOverriddenMethodPopup(null, element) + } + } +} + +private val OVERRIDDEN_PROPERTY = object : MarkerType( "OVERRIDDEN_PROPERTY", { it?.let { getOverriddenPropertyTooltip(it.parent as KtNamedDeclaration) } }, object : LineMarkerNavigator() { override fun browse(e: MouseEvent?, element: PsiElement?) { - element?.let { navigateToPropertyOverriddenDeclarations(e, it.parent as KtProperty) } + buildNavigateToPropertyOverriddenDeclarationsPopup(e, element)?.showPopup(e) } - }) + }) { + + override fun getNavigationHandler(): GutterIconNavigationHandler { + val superHandler = super.getNavigationHandler() + return object : GutterIconNavigationHandler, TestableLineMarkerNavigator { + override fun navigate(e: MouseEvent?, elt: PsiElement?) { + superHandler.navigate(e, elt) + } + + override fun getTargetsPopupDescriptor(element: PsiElement?) = buildNavigateToPropertyOverriddenDeclarationsPopup(null, element) + } + } +} private val PLATFORM_IMPLEMENTATION = MarkerType( "PLATFORM_IMPLEMENTATION", diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenFunctionMarker.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenFunctionMarker.kt index 1b793f4d32a..6386b5d0446 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenFunctionMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenFunctionMarker.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.highlighter.markers import com.intellij.codeInsight.daemon.DaemonBundle import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper -import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask import com.intellij.ide.util.MethodCellRenderer import com.intellij.ide.util.PsiElementListCellRenderer @@ -93,10 +92,12 @@ fun getOverriddenMethodTooltip(method: PsiMethod): String? { return GutterIconTooltipHelper.composeText(overridingJavaMethods, start, "    {1}") } -fun navigateToOverriddenMethod(e: MouseEvent?, method: PsiMethod) { +fun buildNavigateToOverriddenMethodPopup(e: MouseEvent?, element: PsiElement?): NavigationPopupDescriptor? { + val method = getPsiMethod(element) ?: return null + if (DumbService.isDumb(method.project)) { DumbService.getInstance(method.project)?.showDumbModeNotification("Navigation to overriding classes is not possible during index update") - return + return null } val processor = PsiElementProcessor.CollectElementsWithLimit(2, THashSet()) @@ -105,11 +106,11 @@ fun navigateToOverriddenMethod(e: MouseEvent?, method: PsiMethod) { OverridingMethodsSearch.search(method, true).forEach(PsiElementProcessorAdapter(processor)) }, "Searching for overriding declarations", true, method.project, e?.component as JComponent?)) { - return + return null } var overridingJavaMethods = processor.collection.filter { !it.isMethodWithDeclarationInOtherClass() } - if (overridingJavaMethods.isEmpty()) return + if (overridingJavaMethods.isEmpty()) return null val showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridingJavaMethods.toTypedArray()) @@ -117,13 +118,11 @@ fun navigateToOverriddenMethod(e: MouseEvent?, method: PsiMethod) { overridingJavaMethods = overridingJavaMethods.sortedWith(renderer.comparator) val methodsUpdater = OverridingMethodsUpdater(method, renderer) - PsiElementListNavigator.openTargets( - e, - overridingJavaMethods.toTypedArray(), - methodsUpdater.getCaption(overridingJavaMethods.size), - "Overriding declarations of " + method.name, - renderer, - methodsUpdater) + return NavigationPopupDescriptor(overridingJavaMethods, + methodsUpdater.getCaption(overridingJavaMethods.size), + "Overriding declarations of " + method.name, + renderer, + methodsUpdater) } private class OverridingMethodsUpdater( diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt index 99cfec34ed9..ec27a9563b5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.highlighter.markers import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper import com.intellij.codeInsight.daemon.impl.MarkerType -import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator import com.intellij.ide.util.DefaultPsiElementCellRenderer import com.intellij.ide.util.PsiClassListCellRenderer import com.intellij.openapi.progress.ProgressManager @@ -76,18 +75,22 @@ fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? { return GutterIconTooltipHelper.composeText(collectedClasses.sortedWith(PsiClassListCellRenderer().comparator), start, pattern) } -fun navigateToPropertyOverriddenDeclarations(e: MouseEvent?, property: KtProperty) { - val project = property.project +fun buildNavigateToPropertyOverriddenDeclarationsPopup(e: MouseEvent?, element: PsiElement?): NavigationPopupDescriptor? { + val propertyOrParameter = element?.parent as? KtNamedDeclaration ?: return null + val project = propertyOrParameter.project if (DumbService.isDumb(project)) { DumbService.getInstance(project)?.showDumbModeNotification("Navigation to overriding classes is not possible during index update") - return + return null } - val psiPropertyMethods = LightClassUtil.getLightClassPropertyMethods(property) - + val psiPropertyMethods = when(propertyOrParameter) { + is KtProperty -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter) + is KtParameter -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter) + else -> return null + } val elementProcessor = CommonProcessors.CollectUniquesProcessor() - val jetPsiMethodProcessor = Runnable { + val ktPsiMethodProcessor = Runnable { KotlinDefinitionsSearcher.processPropertyImplementationsMethods( psiPropertyMethods, GlobalSearchScope.allScope(project), @@ -95,12 +98,12 @@ fun navigateToPropertyOverriddenDeclarations(e: MouseEvent?, property: KtPropert } if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( - /* runnable */ jetPsiMethodProcessor, + /* runnable */ ktPsiMethodProcessor, MarkerType.SEARCHING_FOR_OVERRIDING_METHODS, /* can be canceled */ true, project, e?.component as JComponent?)) { - return + return null } val renderer = DefaultPsiElementCellRenderer() @@ -108,10 +111,9 @@ fun navigateToPropertyOverriddenDeclarations(e: MouseEvent?, property: KtPropert .sortedWith(renderer.comparator) .filterIsInstance() - PsiElementListNavigator.openTargets(e, - navigatingOverrides.toTypedArray(), - KotlinBundle.message("navigation.title.overriding.property", property.name), - KotlinBundle.message("navigation.findUsages.title.overriding.property", property.name), renderer) + return NavigationPopupDescriptor(navigatingOverrides, + KotlinBundle.message("navigation.title.overriding.property", propertyOrParameter.name), + KotlinBundle.message("navigation.findUsages.title.overriding.property", propertyOrParameter.name), renderer) } diff --git a/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt index e1410559e6f..455c04cf5e2 100644 --- a/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt +++ b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt @@ -8,3 +8,10 @@ open class C( class D : C("") { override val s: String get() = "q" } + +/* +LINEMARKER: Is overridden in
    D +TARGETS: +PrimaryConstructorOpen.kt + override val <1>s: String get() = "q" +*/ diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt index b01ab05a380..c124dd5f994 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractLineMarkersTest.kt @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.ReferenceUtils @@ -115,9 +114,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase() val handler = navigateMarker.navigationHandler if (handler is TestableLineMarkerNavigator) { - val element = navigateMarker.element as KtDeclaration - - val navigateElements = handler.getTargetsPopupDescriptor(element)?.targets?.sortedBy { ReferenceUtils.renderAsGotoImplementation(it) } + val navigateElements = handler.getTargetsPopupDescriptor(navigateMarker.element)?.targets?.sortedBy { ReferenceUtils.renderAsGotoImplementation(it) } val actualNavigationData = NavigationTestUtils.getNavigateElementsText(myFixture.project, navigateElements) UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData)