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.PsiElementFactory
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiType
|
||||
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.LightClassInheritanceHelper
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
@@ -58,4 +63,28 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
|
||||
val thisDescriptor = kotlinOrigin.resolveToDescriptorIfAny() as? ClassDescriptor ?: return false
|
||||
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.Query
|
||||
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.psi.KtClassOrObject
|
||||
|
||||
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
|
||||
val psiClass: PsiClass = when (originalElement) {
|
||||
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() }
|
||||
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) }
|
||||
is PsiClass -> originalElement
|
||||
else -> null
|
||||
} ?: return EmptyQuery.getEmptyQuery()
|
||||
|
||||
+37
-12
@@ -29,14 +29,14 @@ import com.intellij.util.EmptyQuery
|
||||
import com.intellij.util.MergeQuery
|
||||
import com.intellij.util.Processor
|
||||
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.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
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.unsafeResolveToDescriptor
|
||||
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.restrictToKotlinSources
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
||||
@@ -122,6 +119,17 @@ object PsiMethodOverridingHierarchyTraverser: HierarchyTraverser<PsiMethod> {
|
||||
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(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
@@ -133,7 +141,7 @@ private fun forEachKotlinOverride(
|
||||
if (baseDescriptors.isEmpty()) return true
|
||||
|
||||
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 substitutor = getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@forEach
|
||||
baseDescriptors.forEach {
|
||||
@@ -149,16 +157,31 @@ private fun forEachKotlinOverride(
|
||||
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(
|
||||
scope: SearchScope = runReadAction { useScope },
|
||||
processor: (PsiMethod) -> 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
|
||||
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
|
||||
val lightMethods = runReadAction { overrider.toLightMethods() }
|
||||
val lightMethods = runReadAction { overrider.toPossiblyFakeLightMethods() }
|
||||
lightMethods.all { processor(it) }
|
||||
}
|
||||
}
|
||||
@@ -174,9 +197,11 @@ fun PsiMethod.forEachImplementation(
|
||||
fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) {
|
||||
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>() +
|
||||
ktClass.primaryConstructorParameters.filter { it.hasValOrVar() }
|
||||
forEachKotlinOverride(ktClass, members, scope, processor)
|
||||
|
||||
@@ -21,13 +21,11 @@ import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightMethod
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import java.util.*
|
||||
|
||||
fun collectContainingClasses(methods: Collection<PsiMethod>): Set<PsiClass> {
|
||||
@@ -58,7 +56,8 @@ internal fun getPsiMethod(element: PsiElement?): PsiMethod? {
|
||||
return when {
|
||||
element == null -> null
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ 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.getAccessorLightMethods
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
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.caches.resolve.findModuleDescriptor
|
||||
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.isOverridable
|
||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||
import org.jetbrains.kotlin.idea.facet.implementedDescriptor
|
||||
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.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -271,10 +272,7 @@ private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDec
|
||||
val mappingToJava = HashMap<PsiElement, KtNamedDeclaration>()
|
||||
for (property in properties) {
|
||||
if (property.isOverridable()) {
|
||||
val accessorsPsiMethods = property.getAccessorLightMethods()
|
||||
for (psiMethod in accessorsPsiMethods) {
|
||||
mappingToJava.put(psiMethod, property)
|
||||
}
|
||||
property.toPossiblyFakeLightMethods().forEach { mappingToJava.put(it, property) }
|
||||
mappingToJava[property] = property
|
||||
}
|
||||
}
|
||||
@@ -352,7 +350,7 @@ private fun collectOverriddenFunctions(functions: Collection<KtNamedFunction>, r
|
||||
val mappingToJava = HashMap<PsiElement, KtNamedFunction>()
|
||||
for (function in functions) {
|
||||
if (function.isOverridable()) {
|
||||
val method = LightClassUtil.getLightClassMethod(function)
|
||||
val method = LightClassUtil.getLightClassMethod(function) ?: KtFakeLightMethod.get(function)
|
||||
if (method != null) {
|
||||
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.ProgressManager
|
||||
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.PsiElementProcessorAdapter
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.psi.util.PsiFormatUtil
|
||||
import com.intellij.util.CommonProcessors
|
||||
import gnu.trove.THashSet
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
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.forEachOverridingMethod
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import java.awt.event.MouseEvent
|
||||
import java.util.*
|
||||
@@ -50,7 +52,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
|
||||
for (aClass in classes) {
|
||||
aClass.forEachDeclaredMemberOverride { superMember, overridingMember ->
|
||||
ProgressManager.checkCanceled()
|
||||
if (overridingMember.toLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
|
||||
if (overridingMember.toPossiblyFakeLightMethods().any { !it.isMethodWithDeclarationInOtherClass() }) {
|
||||
val declaration = mappingToJava[superMember]
|
||||
if (declaration != null) {
|
||||
mappingToJava.remove(superMember)
|
||||
@@ -67,7 +69,7 @@ internal fun <T> getOverriddenDeclarations(mappingToJava: MutableMap<PsiElement,
|
||||
|
||||
fun getOverriddenMethodTooltip(method: PsiMethod): String? {
|
||||
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)
|
||||
|
||||
@@ -109,15 +111,7 @@ fun buildNavigateToOverriddenMethodPopup(e: MouseEvent?, element: PsiElement?):
|
||||
var overridingJavaMethods = processor.collection.filter { !it.isMethodWithDeclarationInOtherClass() }
|
||||
if (overridingJavaMethods.isEmpty()) return null
|
||||
|
||||
val renderedSignatures = overridingJavaMethods.map {
|
||||
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)
|
||||
val renderer = MethodCellRenderer(false)
|
||||
overridingJavaMethods = overridingJavaMethods.sortedWith(renderer.comparator)
|
||||
|
||||
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.CommonProcessors
|
||||
import com.intellij.util.Function
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.getAccessorLightMethods
|
||||
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.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -50,9 +51,9 @@ fun getOverriddenPropertyTooltip(property: KtNamedDeclaration): String? {
|
||||
Function { method: PsiMethod? -> method?.containingClass }
|
||||
)
|
||||
|
||||
for (method in property.getAccessorLightMethods()) {
|
||||
for (method in property.toPossiblyFakeLightMethods()) {
|
||||
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
|
||||
}
|
||||
|
||||
val psiPropertyMethods = when(propertyOrParameter) {
|
||||
is KtProperty -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
|
||||
is KtParameter -> LightClassUtil.getLightClassPropertyMethods(propertyOrParameter)
|
||||
else -> return null
|
||||
}
|
||||
val psiPropertyMethods = propertyOrParameter.toPossiblyFakeLightMethods()
|
||||
val elementProcessor = CommonProcessors.CollectUniquesProcessor<PsiElement>()
|
||||
val ktPsiMethodProcessor = Runnable {
|
||||
KotlinDefinitionsSearcher.processPropertyImplementationsMethods(
|
||||
|
||||
+14
-25
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||
|
||||
import com.intellij.codeInsight.navigation.MethodImplementationsSearch
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
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.QueryExecutor
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtFakeLightClass
|
||||
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.psi.*
|
||||
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 {
|
||||
val psiMethod = runReadAction { LightClassUtil.getLightClassMethod(function) }
|
||||
return psiMethod?.forEachImplementation(scope, consumer::process) ?: true
|
||||
return runReadAction {
|
||||
function.toPossiblyFakeLightMethods().firstOrNull()?.forEachImplementation(scope, consumer::process) ?: true
|
||||
}
|
||||
}
|
||||
|
||||
private fun processPropertyImplementations(parameter: KtParameter, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(parameter) }
|
||||
|
||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
||||
private fun processPropertyImplementations(declaration: KtNamedDeclaration, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||
return runReadAction {
|
||||
processPropertyImplementationsMethods(declaration.toPossiblyFakeLightMethods(), scope, consumer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processPropertyImplementations(property: KtProperty, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||
val accessorsPsiMethods = runReadAction { LightClassUtil.getLightClassPropertyMethods(property) }
|
||||
|
||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
||||
}
|
||||
|
||||
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
|
||||
fun processPropertyImplementationsMethods(accessors: Iterable<PsiMethod>, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||
return accessors.all { method ->
|
||||
method.forEachOverridingMethod(scope) { implementation ->
|
||||
if (isDelegated(implementation)) return@forEachOverridingMethod true
|
||||
|
||||
val elementToProcess = runReadAction {
|
||||
val mirrorElement = (implementation as? KtLightMethod)?.kotlinOrigin
|
||||
@@ -150,12 +142,9 @@ class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSea
|
||||
}
|
||||
}
|
||||
|
||||
if (!consumer.process(elementToProcess)) {
|
||||
return false
|
||||
}
|
||||
consumer.process(elementToProcess)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ enum class SampleEnum {
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
fun testExpectClassSuperclassFun() {
|
||||
doMultiPlatformTest("common.kt")
|
||||
}
|
||||
|
||||
fun testExpectClassSuperclassProperty() {
|
||||
doMultiPlatformTest("common.kt")
|
||||
}
|
||||
|
||||
fun testExpectClass() {
|
||||
doMultiPlatformTest("common.kt")
|
||||
}
|
||||
|
||||
fun testExpectClassFun() {
|
||||
doMultiPlatformTest("common.kt")
|
||||
}
|
||||
|
||||
fun testExpectClassProperty() {
|
||||
doMultiPlatformTest("common.kt")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user