Misc: Support light-methodless members in overrider search
In particular, support line markers for expect-class members and navigation to expect-class members from corresponding base members
This commit is contained in:
+29
@@ -18,14 +18,19 @@ package org.jetbrains.kotlin.idea.caches.resolve.lightClasses
|
|||||||
|
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElementFactory
|
import com.intellij.psi.PsiElementFactory
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiType
|
||||||
import com.intellij.psi.impl.light.AbstractLightClass
|
import com.intellij.psi.impl.light.AbstractLightClass
|
||||||
|
import com.intellij.psi.impl.light.LightMethod
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
|
import org.jetbrains.kotlin.asJava.classes.LightClassInheritanceHelper
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
@@ -59,3 +64,27 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
|
|||||||
return if (checkDeep) DescriptorUtils.isSubclass(thisDescriptor, baseDescriptor) else DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
|
return if (checkDeep) DescriptorUtils.isSubclass(thisDescriptor, baseDescriptor) else DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KtFakeLightMethod private constructor(
|
||||||
|
val ktDeclaration: KtNamedDeclaration,
|
||||||
|
ktClassOrObject : KtClassOrObject
|
||||||
|
) : LightMethod (
|
||||||
|
ktDeclaration.manager,
|
||||||
|
PsiElementFactory.SERVICE.getInstance(ktDeclaration.project).createMethod(ktDeclaration.name ?: "", PsiType.VOID),
|
||||||
|
KtFakeLightClass(ktClassOrObject),
|
||||||
|
KotlinLanguage.INSTANCE
|
||||||
|
), KtLightElement<KtNamedDeclaration, PsiMethod> {
|
||||||
|
override val kotlinOrigin get() = ktDeclaration
|
||||||
|
override val clsDelegate get() = myMethod
|
||||||
|
|
||||||
|
override fun getNavigationElement() = ktDeclaration
|
||||||
|
override fun getIcon(flags: Int) = ktDeclaration.getIcon(flags)
|
||||||
|
override fun getUseScope() = ktDeclaration.useScope
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun get(ktDeclaration: KtNamedDeclaration): KtFakeLightMethod? {
|
||||||
|
val ktClassOrObject = ktDeclaration.containingClassOrObject ?: return null
|
||||||
|
return KtFakeLightMethod(ktDeclaration, ktClassOrObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -23,12 +23,13 @@ import com.intellij.psi.search.searches.ClassInheritorsSearch
|
|||||||
import com.intellij.util.EmptyQuery
|
import com.intellij.util.EmptyQuery
|
||||||
import com.intellij.util.Query
|
import com.intellij.util.Query
|
||||||
import org.jetbrains.kotlin.asJava.toLightClassWithBuiltinMapping
|
import org.jetbrains.kotlin.asJava.toLightClassWithBuiltinMapping
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
|
||||||
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
|
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
|
||||||
val psiClass: PsiClass = when (originalElement) {
|
val psiClass: PsiClass = when (originalElement) {
|
||||||
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() }
|
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) }
|
||||||
is PsiClass -> originalElement
|
is PsiClass -> originalElement
|
||||||
else -> null
|
else -> null
|
||||||
} ?: return EmptyQuery.getEmptyQuery()
|
} ?: return EmptyQuery.getEmptyQuery()
|
||||||
|
|||||||
+37
-12
@@ -29,14 +29,14 @@ import com.intellij.util.EmptyQuery
|
|||||||
import com.intellij.util.MergeQuery
|
import com.intellij.util.MergeQuery
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import com.intellij.util.Query
|
import com.intellij.util.Query
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
|
||||||
import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod
|
import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||||
@@ -45,10 +45,7 @@ import org.jetbrains.kotlin.idea.search.allScope
|
|||||||
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
||||||
@@ -122,6 +119,17 @@ object PsiMethodOverridingHierarchyTraverser: HierarchyTraverser<PsiMethod> {
|
|||||||
override fun shouldDescend(element: PsiMethod): Boolean = PsiUtil.canBeOverriden(element)
|
override fun shouldDescend(element: PsiMethod): Boolean = PsiUtil.canBeOverriden(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PsiElement.toPossiblyFakeLightMethods(): List<PsiMethod> {
|
||||||
|
if (this is PsiMethod) return listOf(this)
|
||||||
|
|
||||||
|
val element = unwrapped ?: return emptyList()
|
||||||
|
|
||||||
|
val lightMethods = element.toLightMethods()
|
||||||
|
if (lightMethods.isNotEmpty()) return lightMethods
|
||||||
|
|
||||||
|
return if (element is KtNamedDeclaration) listOfNotNull(KtFakeLightMethod.get(element)) else emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun forEachKotlinOverride(
|
private fun forEachKotlinOverride(
|
||||||
ktClass: KtClass,
|
ktClass: KtClass,
|
||||||
members: List<KtNamedDeclaration>,
|
members: List<KtNamedDeclaration>,
|
||||||
@@ -133,7 +141,7 @@ private fun forEachKotlinOverride(
|
|||||||
if (baseDescriptors.isEmpty()) return true
|
if (baseDescriptors.isEmpty()) return true
|
||||||
|
|
||||||
HierarchySearchRequest(ktClass, scope.restrictToKotlinSources(), true).searchInheritors().forEach {
|
HierarchySearchRequest(ktClass, scope.restrictToKotlinSources(), true).searchInheritors().forEach {
|
||||||
val inheritor = (it as? KtLightClass)?.kotlinOrigin ?: return@forEach
|
val inheritor = it.unwrapped as? KtClassOrObject ?: return@forEach
|
||||||
val inheritorDescriptor = runReadAction { inheritor.unsafeResolveToDescriptor() as ClassDescriptor }
|
val inheritorDescriptor = runReadAction { inheritor.unsafeResolveToDescriptor() as ClassDescriptor }
|
||||||
val substitutor = getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@forEach
|
val substitutor = getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@forEach
|
||||||
baseDescriptors.forEach {
|
baseDescriptors.forEach {
|
||||||
@@ -149,16 +157,31 @@ private fun forEachKotlinOverride(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtNamedDeclaration.forEachOverridingElement(
|
||||||
|
scope: SearchScope = runReadAction { useScope },
|
||||||
|
processor: (PsiElement) -> Boolean
|
||||||
|
): Boolean {
|
||||||
|
val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true
|
||||||
|
|
||||||
|
toLightMethods().forEach {
|
||||||
|
if (!OverridingMethodsSearch.search(it, scope.excludeKotlinSources(), true).all(processor)) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return forEachKotlinOverride(ktClass, listOf(this), scope) { _, overrider -> processor(overrider) }
|
||||||
|
}
|
||||||
|
|
||||||
fun PsiMethod.forEachOverridingMethod(
|
fun PsiMethod.forEachOverridingMethod(
|
||||||
scope: SearchScope = runReadAction { useScope },
|
scope: SearchScope = runReadAction { useScope },
|
||||||
processor: (PsiMethod) -> Boolean
|
processor: (PsiMethod) -> Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
|
if (this !is KtFakeLightMethod) {
|
||||||
|
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
|
||||||
|
}
|
||||||
|
|
||||||
val ktMember = (this as? KtLightMethod)?.kotlinOrigin as? KtNamedDeclaration ?: return true
|
val ktMember = this.unwrapped as? KtNamedDeclaration ?: return true
|
||||||
val ktClass = runReadAction { ktMember.containingClassOrObject as? KtClass } ?: return true
|
val ktClass = runReadAction { ktMember.containingClassOrObject as? KtClass } ?: return true
|
||||||
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
|
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
|
||||||
val lightMethods = runReadAction { overrider.toLightMethods() }
|
val lightMethods = runReadAction { overrider.toPossiblyFakeLightMethods() }
|
||||||
lightMethods.all { processor(it) }
|
lightMethods.all { processor(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,9 +197,11 @@ fun PsiMethod.forEachImplementation(
|
|||||||
fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) {
|
fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) {
|
||||||
val scope = runReadAction { useScope }
|
val scope = runReadAction { useScope }
|
||||||
|
|
||||||
AllOverridingMethodsSearch.search(this, scope.excludeKotlinSources()).all { processor(it.first, it.second) }
|
if (this !is KtFakeLightClass) {
|
||||||
|
AllOverridingMethodsSearch.search(this, scope.excludeKotlinSources()).all { processor(it.first, it.second) }
|
||||||
|
}
|
||||||
|
|
||||||
val ktClass = (this as? KtLightClass)?.kotlinOrigin as? KtClass ?: return
|
val ktClass = unwrapped as? KtClass ?: return
|
||||||
val members = ktClass.declarations.filterIsInstance<KtNamedDeclaration>() +
|
val members = ktClass.declarations.filterIsInstance<KtNamedDeclaration>() +
|
||||||
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
|
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
|
||||||
forEachKotlinOverride(ktClass, members, scope, processor)
|
forEachKotlinOverride(ktClass, members, scope, processor)
|
||||||
|
|||||||
@@ -21,13 +21,11 @@ import com.intellij.psi.CommonClassNames
|
|||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.*
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
|
||||||
import org.jetbrains.kotlin.psi.KtFunction
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun collectContainingClasses(methods: Collection<PsiMethod>): Set<PsiClass> {
|
fun collectContainingClasses(methods: Collection<PsiMethod>): Set<PsiClass> {
|
||||||
@@ -58,7 +56,8 @@ internal fun getPsiMethod(element: PsiElement?): PsiMethod? {
|
|||||||
return when {
|
return when {
|
||||||
element == null -> null
|
element == null -> null
|
||||||
element is PsiMethod -> element
|
element is PsiMethod -> element
|
||||||
parent is KtNamedFunction || parent is KtSecondaryConstructor -> LightClassUtil.getLightClassMethod(parent as KtFunction)
|
parent is KtNamedFunction || parent is KtSecondaryConstructor ->
|
||||||
|
LightClassUtil.getLightClassMethod(parent as KtFunction) ?: KtFakeLightMethod.get(parent)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import com.intellij.psi.PsiMethod
|
|||||||
import com.intellij.psi.PsiNameIdentifierOwner
|
import com.intellij.psi.PsiNameIdentifierOwner
|
||||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
|
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
@@ -42,11 +41,13 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
|
||||||
import org.jetbrains.kotlin.idea.core.isInheritable
|
import org.jetbrains.kotlin.idea.core.isInheritable
|
||||||
import org.jetbrains.kotlin.idea.core.isOverridable
|
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
import org.jetbrains.kotlin.idea.facet.implementedDescriptor
|
import org.jetbrains.kotlin.idea.facet.implementedDescriptor
|
||||||
import org.jetbrains.kotlin.idea.facet.implementingDescriptors
|
import org.jetbrains.kotlin.idea.facet.implementingDescriptors
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -271,10 +272,7 @@ private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDec
|
|||||||
val mappingToJava = HashMap<PsiElement, KtNamedDeclaration>()
|
val mappingToJava = HashMap<PsiElement, KtNamedDeclaration>()
|
||||||
for (property in properties) {
|
for (property in properties) {
|
||||||
if (property.isOverridable()) {
|
if (property.isOverridable()) {
|
||||||
val accessorsPsiMethods = property.getAccessorLightMethods()
|
property.toPossiblyFakeLightMethods().forEach { mappingToJava.put(it, property) }
|
||||||
for (psiMethod in accessorsPsiMethods) {
|
|
||||||
mappingToJava.put(psiMethod, property)
|
|
||||||
}
|
|
||||||
mappingToJava[property] = property
|
mappingToJava[property] = property
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,7 +350,7 @@ private fun collectOverriddenFunctions(functions: Collection<KtNamedFunction>, r
|
|||||||
val mappingToJava = HashMap<PsiElement, KtNamedFunction>()
|
val mappingToJava = HashMap<PsiElement, KtNamedFunction>()
|
||||||
for (function in functions) {
|
for (function in functions) {
|
||||||
if (function.isOverridable()) {
|
if (function.isOverridable()) {
|
||||||
val method = LightClassUtil.getLightClassMethod(function)
|
val method = LightClassUtil.getLightClassMethod(function) ?: KtFakeLightMethod.get(function)
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
mappingToJava.put(method, function)
|
mappingToJava.put(method, function)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,18 +24,20 @@ import com.intellij.ide.util.PsiElementListCellRenderer
|
|||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiModifier
|
||||||
import com.intellij.psi.search.PsiElementProcessor
|
import com.intellij.psi.search.PsiElementProcessor
|
||||||
import com.intellij.psi.search.PsiElementProcessorAdapter
|
import com.intellij.psi.search.PsiElementProcessorAdapter
|
||||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||||
import com.intellij.psi.util.PsiFormatUtil
|
|
||||||
import com.intellij.util.CommonProcessors
|
import com.intellij.util.CommonProcessors
|
||||||
import gnu.trove.THashSet
|
import gnu.trove.THashSet
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.elements.isTraitFakeOverride
|
import org.jetbrains.kotlin.asJava.elements.isTraitFakeOverride
|
||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachDeclaredMemberOverride
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachDeclaredMemberOverride
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import java.awt.event.MouseEvent
|
import java.awt.event.MouseEvent
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -50,7 +52,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
|
|||||||
for (aClass in classes) {
|
for (aClass in classes) {
|
||||||
aClass.forEachDeclaredMemberOverride { superMember, overridingMember ->
|
aClass.forEachDeclaredMemberOverride { superMember, overridingMember ->
|
||||||
ProgressManager.checkCanceled()
|
ProgressManager.checkCanceled()
|
||||||
if (overridingMember.toLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
|
if (overridingMember.toPossiblyFakeLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
|
||||||
val declaration = mappingToJava[superMember]
|
val declaration = mappingToJava[superMember]
|
||||||
if (declaration != null) {
|
if (declaration != null) {
|
||||||
mappingToJava.remove(superMember)
|
mappingToJava.remove(superMember)
|
||||||
@@ -67,7 +69,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
|
|||||||
|
|
||||||
fun getOverriddenMethodTooltip(method: PsiMethod): String? {
|
fun getOverriddenMethodTooltip(method: PsiMethod): String? {
|
||||||
val processor = PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5)
|
val processor = PsiElementProcessor.CollectElementsWithLimit<PsiMethod>(5)
|
||||||
OverridingMethodsSearch.search(method, true).forEach(PsiElementProcessorAdapter(processor))
|
method.forEachOverridingMethod(processor = PsiElementProcessorAdapter(processor)::process)
|
||||||
|
|
||||||
val isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT)
|
val isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT)
|
||||||
|
|
||||||
@@ -109,15 +111,7 @@ fun buildNavigateToOverriddenMethodPopup(e: MouseEvent?, element: PsiElement?):
|
|||||||
var overridingJavaMethods = processor.collection.filter { !it.isMethodWithDeclarationInOtherClass() }
|
var overridingJavaMethods = processor.collection.filter { !it.isMethodWithDeclarationInOtherClass() }
|
||||||
if (overridingJavaMethods.isEmpty()) return null
|
if (overridingJavaMethods.isEmpty()) return null
|
||||||
|
|
||||||
val renderedSignatures = overridingJavaMethods.map {
|
val renderer = MethodCellRenderer(false)
|
||||||
PsiFormatUtil.formatMethod(it,
|
|
||||||
PsiSubstitutor.EMPTY,
|
|
||||||
PsiFormatUtil.SHOW_PARAMETERS + PsiFormatUtil.SHOW_FQ_CLASS_NAMES,
|
|
||||||
PsiFormatUtil.SHOW_TYPE + PsiFormatUtil.SHOW_FQ_CLASS_NAMES)
|
|
||||||
}
|
|
||||||
val showMethodNames = renderedSignatures.distinct().size > 1
|
|
||||||
|
|
||||||
val renderer = MethodCellRenderer(showMethodNames)
|
|
||||||
overridingJavaMethods = overridingJavaMethods.sortedWith(renderer.comparator)
|
overridingJavaMethods = overridingJavaMethods.sortedWith(renderer.comparator)
|
||||||
|
|
||||||
val methodsUpdater = OverridingMethodsUpdater(method, renderer)
|
val methodsUpdater = OverridingMethodsUpdater(method, renderer)
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch
|
|||||||
import com.intellij.util.AdapterProcessor
|
import com.intellij.util.AdapterProcessor
|
||||||
import com.intellij.util.CommonProcessors
|
import com.intellij.util.CommonProcessors
|
||||||
import com.intellij.util.Function
|
import com.intellij.util.Function
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
|
||||||
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
|
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher
|
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -50,9 +51,9 @@ fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? {
|
|||||||
Function { method: PsiMethod? -> method?.containingClass }
|
Function { method: PsiMethod? -> method?.containingClass }
|
||||||
)
|
)
|
||||||
|
|
||||||
for (method in property.getAccessorLightMethods()) {
|
for (method in property.toPossiblyFakeLightMethods()) {
|
||||||
if (!overriddenInClassesProcessor.isOverflow) {
|
if (!overriddenInClassesProcessor.isOverflow) {
|
||||||
OverridingMethodsSearch.search(method, true).forEach(consumer)
|
method.forEachOverridingMethod(processor = consumer::process)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,11 +86,7 @@ fun buildNavigateToPropertyOverriddenDeclarationsPopup(e: MouseEvent?, element:
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val psiPropertyMethods = when(propertyOrParameter) {
|
val psiPropertyMethods = propertyOrParameter.toPossiblyFakeLightMethods()
|
||||||
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
|
|
||||||
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
val elementProcessor = CommonProcessors.CollectUniquesProcessor<PsiElement>()
|
val elementProcessor = CommonProcessors.CollectUniquesProcessor<PsiElement>()
|
||||||
val ktPsiMethodProcessor = Runnable {
|
val ktPsiMethodProcessor = Runnable {
|
||||||
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(
|
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(
|
||||||
|
|||||||
+14
-25
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||||
|
|
||||||
import com.intellij.codeInsight.navigation.MethodImplementationsSearch
|
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
@@ -28,13 +27,14 @@ import com.intellij.psi.search.searches.DefinitionsScopedSearch
|
|||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import com.intellij.util.QueryExecutor
|
import com.intellij.util.QueryExecutor
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachImplementation
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachImplementation
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.contains
|
import org.jetbrains.kotlin.psi.psiUtil.contains
|
||||||
@@ -117,29 +117,21 @@ class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSea
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processFunctionImplementations(function: KtFunction, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
private fun processFunctionImplementations(function: KtFunction, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
val psiMethod = runReadAction { LightClassUtil.getLightClassMethod(function) }
|
return runReadAction {
|
||||||
return psiMethod?.forEachImplementation(scope, consumer::process) ?: true
|
function.toPossiblyFakeLightMethods().firstOrNull()?.forEachImplementation(scope, consumer::process) ?: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPropertyImplementations(parameter: KtParameter, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
private fun processPropertyImplementations(declaration: KtNamedDeclaration, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(parameter) }
|
return runReadAction {
|
||||||
|
processPropertyImplementationsMethods(declaration.toPossiblyFakeLightMethods(), scope, consumer)
|
||||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPropertyImplementations(property: KtProperty, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
fun processPropertyImplementationsMethods(accessors: Iterable<PsiMethod>, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(property) }
|
return accessors.all { method ->
|
||||||
|
method.forEachOverridingMethod(scope) { implementation ->
|
||||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
if (isDelegated(implementation)) return@forEachOverridingMethod true
|
||||||
}
|
|
||||||
|
|
||||||
fun processPropertyImplementationsMethods(accessors: LightClassUtil.PropertyAccessorsPsiMethods, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
|
||||||
for (method in accessors) {
|
|
||||||
val implementations = ArrayList<PsiMethod>()
|
|
||||||
MethodImplementationsSearch.getOverridingMethods(method, implementations, scope)
|
|
||||||
|
|
||||||
for (implementation in implementations) {
|
|
||||||
if (isDelegated(implementation)) continue
|
|
||||||
|
|
||||||
val elementToProcess = runReadAction {
|
val elementToProcess = runReadAction {
|
||||||
val mirrorElement = (implementation as? KtLightMethod)?.kotlinOrigin
|
val mirrorElement = (implementation as? KtLightMethod)?.kotlinOrigin
|
||||||
@@ -150,12 +142,9 @@ class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consumer.process(elementToProcess)) {
|
consumer.process(elementToProcess)
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ enum class SampleEnum {
|
|||||||
override fun <lineMarker descr="Overrides function in 'SampleEnum'">any</lineMarker>() { super.any() }
|
override fun <lineMarker descr="Overrides function in 'SampleEnum'">any</lineMarker>() { super.any() }
|
||||||
};
|
};
|
||||||
|
|
||||||
open fun <lineMarker descr="<html><body>Is overridden in <br> Enum constant 'V1' in 'SampleEnum'</body></html>">any</lineMarker>() {}
|
open fun <lineMarker descr="<html><body>Is overridden in <br> SampleEnum.V1</body></html>">any</lineMarker>() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-4
@@ -1,9 +1,21 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
open class <lineMarker>SimpleParent</lineMarker>
|
open class <lineMarker>SimpleParent</lineMarker> {
|
||||||
|
open fun <lineMarker>foo</lineMarker>(n: Int) {}
|
||||||
|
open val <lineMarker>bar</lineMarker>: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
expect open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent
|
expect open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent {
|
||||||
|
override fun <lineMarker><lineMarker>foo</lineMarker></lineMarker>(n: Int)
|
||||||
|
override val <lineMarker><lineMarker>bar</lineMarker></lineMarker>: Int
|
||||||
|
}
|
||||||
|
|
||||||
class ExpectedChildChild : ExpectedChild()
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override fun <lineMarker>foo</lineMarker>(n: Int) {}
|
||||||
|
override val <lineMarker>bar</lineMarker>: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
class SimpleChild : SimpleParent()
|
class SimpleChild : SimpleParent() {
|
||||||
|
override fun <lineMarker>foo</lineMarker>(n: Int) {}
|
||||||
|
override val <lineMarker>bar</lineMarker>: Int get() = 1
|
||||||
|
}
|
||||||
+8
-2
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
actual open class ExpectedChild : SimpleParent()
|
actual open class ExpectedChild : SimpleParent() {
|
||||||
|
actual override fun foo(n: Int) {}
|
||||||
|
actual override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
class ExpectedChildChildJvm : ExpectedChild()
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
+16
-4
@@ -2,10 +2,22 @@
|
|||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
open class <caret>SimpleParent
|
open class SimpleParent {
|
||||||
|
open fun foo(n: Int) {}
|
||||||
|
open val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
expect open class ExpectedChild : SimpleParent
|
expect open class ExpectedChild : SimpleParent {
|
||||||
|
override fun foo(n: Int)
|
||||||
|
override val bar: Int
|
||||||
|
}
|
||||||
|
|
||||||
class ExpectedChildChild : ExpectedChild()
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
class SimpleChild : SimpleParent()
|
class SimpleChild : SimpleParent() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
+8
-2
@@ -1,5 +1,11 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
actual open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent()
|
actual open class <lineMarker><lineMarker>ExpectedChild</lineMarker></lineMarker> : SimpleParent() {
|
||||||
|
actual override fun <lineMarker><lineMarker><lineMarker>foo</lineMarker></lineMarker></lineMarker>(n: Int) {}
|
||||||
|
actual override val <lineMarker><lineMarker><lineMarker>bar</lineMarker></lineMarker></lineMarker>: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
class ExpectedChildChildJvm : ExpectedChild()
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override fun <lineMarker>foo</lineMarker>(n: Int) {}
|
||||||
|
override val <lineMarker>bar</lineMarker>: Int get() = 1
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
open class SimpleParent {
|
||||||
|
open fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect open class ExpectedChild : SimpleParent {
|
||||||
|
override fun <caret>foo(n: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleChild : SimpleParent() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// REF: [common] (in test.ExpectedChildChild).foo(Int)
|
||||||
|
// REF: [jvm] (in test.ExpectedChildChildJvm).foo(Int)
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
actual open class ExpectedChild : SimpleParent() {
|
||||||
|
actual override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
open class SimpleParent {
|
||||||
|
open val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
expect open class ExpectedChild : SimpleParent {
|
||||||
|
override val <caret>bar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleChild : SimpleParent() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// REF: [common] (in test.ExpectedChildChild).bar
|
||||||
|
// REF: [jvm] (in test.ExpectedChildChildJvm).bar
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
actual open class ExpectedChild : SimpleParent() {
|
||||||
|
actual override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
open class SimpleParent {
|
||||||
|
open fun <caret>foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect open class ExpectedChild : SimpleParent {
|
||||||
|
override fun foo(n: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleChild : SimpleParent() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// REF: [common] (in test.ExpectedChild).foo(Int)
|
||||||
|
// REF: [common] (in test.ExpectedChildChild).foo(Int)
|
||||||
|
// REF: [common] (in test.SimpleChild).foo(Int)
|
||||||
|
// REF: [jvm] (in test.ExpectedChild).foo(Int)
|
||||||
|
// REF: [jvm] (in test.ExpectedChildChildJvm).foo(Int)
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
actual open class ExpectedChild : SimpleParent() {
|
||||||
|
actual override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override fun foo(n: Int) {}
|
||||||
|
}
|
||||||
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
open class SimpleParent {
|
||||||
|
open val <caret>bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
expect open class ExpectedChild : SimpleParent {
|
||||||
|
override val bar: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChild : ExpectedChild() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleChild : SimpleParent() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// REF: [common] (in test.ExpectedChild).bar
|
||||||
|
// REF: [common] (in test.ExpectedChildChild).bar
|
||||||
|
// REF: [common] (in test.SimpleChild).bar
|
||||||
|
// REF: [jvm] (in test.ExpectedChild).bar
|
||||||
|
// REF: [jvm] (in test.ExpectedChildChildJvm).bar
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
actual open class ExpectedChild : SimpleParent() {
|
||||||
|
actual override val bar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpectedChildChildJvm : ExpectedChild() {
|
||||||
|
override val bar: Int get() = 1
|
||||||
|
}
|
||||||
+16
@@ -72,7 +72,23 @@ class KotlinGotoImplementationMultiModuleTest : AbstractMultiModuleTest() {
|
|||||||
doMultiPlatformTest("common.kt")
|
doMultiPlatformTest("common.kt")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testExpectClassSuperclassFun() {
|
||||||
|
doMultiPlatformTest("common.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testExpectClassSuperclassProperty() {
|
||||||
|
doMultiPlatformTest("common.kt")
|
||||||
|
}
|
||||||
|
|
||||||
fun testExpectClass() {
|
fun testExpectClass() {
|
||||||
doMultiPlatformTest("common.kt")
|
doMultiPlatformTest("common.kt")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testExpectClassFun() {
|
||||||
|
doMultiPlatformTest("common.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testExpectClassProperty() {
|
||||||
|
doMultiPlatformTest("common.kt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user