show line markers for properties defined in the primary constructor (KT-12626)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+25
-11
@@ -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<KtNamedFunction>()
|
||||
val properties = HashSet<KtProperty>()
|
||||
val properties = HashSet<KtNamedDeclaration>()
|
||||
|
||||
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<LineMarkerInfo<*>>) {
|
||||
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<KtProperty>, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||
val mappingToJava = HashMap<PsiMethod, KtProperty>()
|
||||
private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDeclaration>,
|
||||
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||
val mappingToJava = HashMap<PsiMethod, KtNamedDeclaration>()
|
||||
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<KtProperty
|
||||
for (property in getOverriddenDeclarations(mappingToJava, classes)) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
val anchor = property.nameIdentifier ?: property
|
||||
val anchor = (property as? PsiNameIdentifierOwner)?.nameIdentifier ?: property
|
||||
|
||||
result.add(LineMarkerInfo(
|
||||
anchor,
|
||||
@@ -190,6 +196,14 @@ private fun collectOverriddenPropertyAccessors(properties: Collection<KtProperty
|
||||
}
|
||||
}
|
||||
|
||||
fun KtNamedDeclaration.getAccessorLightMethods(): LightClassUtil.PropertyAccessorsPsiMethods {
|
||||
return when (this) {
|
||||
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(this)
|
||||
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(this)
|
||||
else -> throw IllegalStateException("Unexpected property type: ${this}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectOverriddenFunctions(functions: Collection<KtNamedFunction>, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||
val mappingToJava = HashMap<PsiMethod, KtNamedFunction>()
|
||||
for (function in functions) {
|
||||
|
||||
@@ -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<PsiClass>(5)
|
||||
|
||||
val consumer = AdapterProcessor<PsiMethod, PsiClass>(
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<KtDeclaration, String> {
|
||||
override fun `fun`(ktDeclaration: KtDeclaration?): String? {
|
||||
@@ -112,7 +112,10 @@ data class ResolveWithParentsResult(
|
||||
val overriddenDescriptors: Collection<CallableMemberDescriptor>)
|
||||
|
||||
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())
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
open class <lineMarker></lineMarker>C(
|
||||
open val <lineMarker descr="<html><body>Is overridden in <br/> D</body></html>"></lineMarker>s: String
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
class D : C("") {
|
||||
override val <lineMarker></lineMarker>s: String get() = "q"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
interface <lineMarker></lineMarker>I {
|
||||
val <lineMarker></lineMarker>name: String
|
||||
}
|
||||
|
||||
class D(
|
||||
override val <lineMarker descr="Implements property in 'I'"></lineMarker>name: String
|
||||
): I
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user