From e22404176088f195bca2acd2a62efe00f6da806b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 14 Jul 2016 15:49:26 +0200 Subject: [PATCH] show line markers for properties defined in the primary constructor (KT-12626) --- .../jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt | 7 +++- .../markers/KotlinLineMarkerProvider.kt | 36 ++++++++++++------ .../markers/OverridenPropertyMarker.kt | 38 +++++++++---------- .../markers/SuperDeclarationMarker.kt | 11 ++++-- .../PrimaryConstructorOpen.kt | 10 +++++ .../PrimaryConstructorOverride.kt | 7 ++++ .../codeInsight/LineMarkersTestGenerated.java | 12 ++++++ 7 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt create mode 100644 idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt index c50094f88c9..22c65364306 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt @@ -180,8 +180,11 @@ fun KtDeclaration.isOverridable(): Boolean { val parent = parent if (!(parent is KtClassBody || parent is KtParameterList)) return false - val klass = parent.parent as? KtClass ?: return false - if (!klass.isInheritable() && !klass.isEnum()) return false + val klass = if (parent.parent is KtPrimaryConstructor) + parent.parent.parent as? KtClass + else + parent.parent as? KtClass + if (klass == null || (!klass.isInheritable() && !klass.isEnum())) return false if (hasModifier(KtTokens.FINAL_KEYWORD) || hasModifier(KtTokens.PRIVATE_KEYWORD)) return false 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 8a2c3e86c43..241653b0088 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/KotlinLineMarkerProvider.kt @@ -27,6 +27,7 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.DumbService import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.search.searches.ClassInheritorsSearch import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.toLightClass @@ -34,10 +35,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isOverridable import java.awt.event.MouseEvent import java.util.* @@ -56,7 +54,7 @@ class KotlinLineMarkerProvider : LineMarkerProvider { if (DumbService.getInstance(first.project).isDumb || !ProjectRootsUtil.isInProjectOrLibSource(first)) return val functions = HashSet() - val properties = HashSet() + val properties = HashSet() for (element in elements) { ProgressManager.checkCanceled() @@ -73,6 +71,12 @@ class KotlinLineMarkerProvider : LineMarkerProvider { properties.add(element) collectSuperDeclarationMarkers(element, result) } + is KtParameter -> { + if (element.hasValOrVar()) { + properties.add(element) + collectSuperDeclarationMarkers(element, result) + } + } } } @@ -103,7 +107,7 @@ private val OVERRIDDEN_FUNCTION = MarkerType( }) private val OVERRIDDEN_PROPERTY = MarkerType( - { it?.let { getOverriddenPropertyTooltip(it.parent as KtProperty) } }, + { it?.let { getOverriddenPropertyTooltip(it.parent as KtNamedDeclaration) } }, object : LineMarkerNavigator() { override fun browse(e: MouseEvent?, element: PsiElement?) { element?.let { navigateToPropertyOverriddenDeclarations(e, it.parent as KtProperty) } @@ -115,7 +119,7 @@ private fun isImplementsAndNotOverrides(descriptor: CallableMemberDescriptor, ov } private fun collectSuperDeclarationMarkers(declaration: KtDeclaration, result: MutableCollection>) { - assert(declaration is KtNamedFunction || declaration is KtProperty) + assert(declaration is KtNamedFunction || declaration is KtProperty || declaration is KtParameter) if (!declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return @@ -160,11 +164,13 @@ private fun collectInheritedClassMarker(element: KtClass, result: MutableCollect )) } -private fun collectOverriddenPropertyAccessors(properties: Collection, result: MutableCollection>) { - val mappingToJava = HashMap() +private fun collectOverriddenPropertyAccessors(properties: Collection, + result: MutableCollection>) { + val mappingToJava = HashMap() for (property in properties) { if (property.isOverridable()) { - val accessorsPsiMethods = LightClassUtil.getLightClassPropertyMethods(property) + val accessorsPsiMethods = property.getAccessorLightMethods() + for (psiMethod in accessorsPsiMethods) { mappingToJava.put(psiMethod, property) } @@ -176,7 +182,7 @@ private fun collectOverriddenPropertyAccessors(properties: Collection LightClassUtil.getLightClassPropertyMethods(this) + is KtParameter -> LightClassUtil.getLightClassPropertyMethods(this) + else -> throw IllegalStateException("Unexpected property type: ${this}") + } +} + private fun collectOverriddenFunctions(functions: Collection, result: MutableCollection>) { val mappingToJava = HashMap() for (function in functions) { 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 793e5378ef6..72c09031224 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/OverridenPropertyMarker.kt @@ -16,33 +16,33 @@ package org.jetbrains.kotlin.idea.highlighter.markers -import com.intellij.psi.search.PsiElementProcessor -import com.intellij.psi.PsiClass -import org.jetbrains.kotlin.idea.KotlinBundle -import com.intellij.psi.search.searches.OverridingMethodsSearch -import org.jetbrains.kotlin.asJava.LightClassUtil -import com.intellij.psi.PsiMethod -import com.intellij.util.AdapterProcessor -import com.intellij.util.CommonProcessors -import com.intellij.psi.search.PsiElementProcessorAdapter import com.intellij.codeInsight.daemon.impl.GutterIconTooltipHelper -import com.intellij.psi.PsiElement -import java.awt.event.MouseEvent -import com.intellij.openapi.project.DumbService -import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.openapi.progress.ProgressManager 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 javax.swing.JComponent -import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.project.DumbService import com.intellij.psi.NavigatablePsiElement +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiElementProcessor +import com.intellij.psi.search.PsiElementProcessorAdapter +import com.intellij.psi.search.searches.OverridingMethodsSearch +import com.intellij.util.AdapterProcessor +import com.intellij.util.CommonProcessors import com.intellij.util.Function +import org.jetbrains.kotlin.asJava.LightClassUtil +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* +import java.awt.event.MouseEvent +import javax.swing.JComponent -fun getOverriddenPropertyTooltip(property: KtProperty): String? { +fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? { val overriddenInClassesProcessor = PsiElementProcessor.CollectElementsWithLimit(5) val consumer = AdapterProcessor( @@ -50,7 +50,7 @@ fun getOverriddenPropertyTooltip(property: KtProperty): String? { Function { method: PsiMethod? -> method?.containingClass } ) - for (method in LightClassUtil.getLightClassPropertyMethods(property)) { + for (method in property.getAccessorLightMethods()) { if (!overriddenInClassesProcessor.isOverflow) { OverridingMethodsSearch.search(method, true).forEach(consumer) } diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt index eccdc9f3b97..77fa867e800 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt @@ -27,17 +27,17 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.idea.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.KtFunctionPsiElementCellRenderer +import org.jetbrains.kotlin.idea.search.usagesSearch.propertyDescriptor import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.RenderingFormat -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.OverrideResolver import java.awt.event.MouseEvent -import java.util.ArrayList +import java.util.* object SuperDeclarationMarkerTooltip: Function { override fun `fun`(ktDeclaration: KtDeclaration?): String? { @@ -112,7 +112,10 @@ data class ResolveWithParentsResult( val overriddenDescriptors: Collection) fun resolveDeclarationWithParents(element: KtDeclaration): ResolveWithParentsResult { - val descriptor = element.resolveToDescriptorIfAny() + val descriptor = if (element is KtParameter) + element.propertyDescriptor + else + element.resolveToDescriptorIfAny() if (descriptor !is CallableMemberDescriptor) return ResolveWithParentsResult(null, listOf()) diff --git a/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt new file mode 100644 index 00000000000..dd36a88e504 --- /dev/null +++ b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt @@ -0,0 +1,10 @@ +open class C( + open val s: String +) { + +} + + +class D : C("") { + override val s: String get() = "q" +} diff --git a/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt new file mode 100644 index 00000000000..15328a8fe08 --- /dev/null +++ b/idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt @@ -0,0 +1,7 @@ +interface I { + val name: String +} + +class D( + override val name: String +): I diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java index 6e737251ffe..4dd5f971c91 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LineMarkersTestGenerated.java @@ -163,6 +163,18 @@ public class LineMarkersTestGenerated extends AbstractLineMarkersTest { doTest(fileName); } + @TestMetadata("PrimaryConstructorOpen.kt") + public void testPrimaryConstructorOpen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOpen.kt"); + doTest(fileName); + } + + @TestMetadata("PrimaryConstructorOverride.kt") + public void testPrimaryConstructorOverride() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/overrideImplement/PrimaryConstructorOverride.kt"); + doTest(fileName); + } + @TestMetadata("PropertyOverride.kt") public void testPropertyOverride() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/overrideImplement/PropertyOverride.kt");