diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/GotoSuperActionHandler.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/GotoSuperActionHandler.kt index 1c75058c0cf..7c95e55352b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/GotoSuperActionHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/GotoSuperActionHandler.kt @@ -28,28 +28,60 @@ import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class GotoSuperActionHandler : CodeInsightActionHandler { - internal fun allSuperDeclarationsAndDescriptor(editor: Editor, file: PsiFile): Pair, DeclarationDescriptor?> { - val element = file.findElementAt(editor.caretModel.offset) ?: return emptyList() to null - val declaration = - PsiTreeUtil.getParentOfType( - element, - KtNamedFunction::class.java, - KtClass::class.java, - KtProperty::class.java, - KtObjectDeclaration::class.java - ) ?: return emptyList() to null + internal data class SuperDeclarationsAndDescriptor(val supers: List, val descriptor: DeclarationDescriptor?) { + constructor() : this(emptyList(), null) - val expectDeclaration = if (declaration.hasActualModifier()) declaration.expectedDeclarationIfAny() else null + companion object { + fun forDeclarationAtCaret(editor: Editor, file: PsiFile): SuperDeclarationsAndDescriptor { + val element = file.findElementAt(editor.caretModel.offset) ?: return SuperDeclarationsAndDescriptor() + val declaration = + PsiTreeUtil.getParentOfType( + element, + KtNamedFunction::class.java, + KtClass::class.java, + KtProperty::class.java, + KtObjectDeclaration::class.java + ) ?: return SuperDeclarationsAndDescriptor() - val descriptor = declaration.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) - val superDeclarations = findSuperDeclarations(file.project, descriptor) - return ((superDeclarations ?: emptyList()) + listOfNotNull(expectDeclaration)) to descriptor + val expectDeclaration = if (declaration.hasActualModifier()) declaration.expectedDeclarationIfAny() else null + + val descriptor = declaration.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) + val superDeclarations = findSuperDeclarations(file.project, descriptor) + return SuperDeclarationsAndDescriptor( + supers = (superDeclarations ?: emptyList()) + listOfNotNull(expectDeclaration), + descriptor = descriptor + ) + } + + private fun findSuperDeclarations(project: Project, descriptor: DeclarationDescriptor): List? { + val superDescriptors: Collection = when (descriptor) { + is ClassDescriptor -> { + val supertypes = descriptor.typeConstructor.supertypes + val superclasses = supertypes.mapNotNull { type -> + type.constructor.declarationDescriptor as? ClassDescriptor + } + ContainerUtil.removeDuplicates(superclasses) + superclasses + } + is CallableMemberDescriptor -> descriptor.getDirectlyOverriddenDeclarations() + else -> return null + } + + return superDescriptors.mapNotNull { superDescriptor -> + if (superDescriptor is ClassDescriptor && isAny(superDescriptor)) { + null + } else + DescriptorToSourceUtilsIde.getAnyDeclaration(project, superDescriptor) + } + } + + } } override fun invoke(project: Project, editor: Editor, file: PsiFile) { FeatureUsageTracker.getInstance().triggerFeatureUsed(GotoSuperAction.FEATURE_ID) - val (allDeclarations, descriptor) = allSuperDeclarationsAndDescriptor(editor, file) + val (allDeclarations, descriptor) = SuperDeclarationsAndDescriptor.forDeclarationAtCaret(editor, file) if (allDeclarations.isEmpty()) return if (allDeclarations.size == 1) { val navigatable = EditSourceUtil.getDescriptor(allDeclarations[0]) @@ -78,27 +110,5 @@ class GotoSuperActionHandler : CodeInsightActionHandler { else -> null } - private fun findSuperDeclarations(project: Project, descriptor: DeclarationDescriptor): List? { - val superDescriptors: Collection = when (descriptor) { - is ClassDescriptor -> { - val supertypes = descriptor.typeConstructor.supertypes - val superclasses = supertypes.mapNotNull { type -> - type.constructor.declarationDescriptor as? ClassDescriptor - } - ContainerUtil.removeDuplicates(superclasses) - superclasses - } - is CallableMemberDescriptor -> descriptor.getDirectlyOverriddenDeclarations() - else -> return null - } - - return superDescriptors.mapNotNull { descriptor -> - if (descriptor is ClassDescriptor && isAny(descriptor)) { - null - } else - DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) - } - } - override fun startInWriteAction() = false } diff --git a/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoSuperMultiModuleTest.kt b/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoSuperMultiModuleTest.kt index 26836faffe0..bd4006d4d16 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoSuperMultiModuleTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/navigation/KotlinGotoSuperMultiModuleTest.kt @@ -14,8 +14,7 @@ import java.io.File class KotlinGotoSuperMultiModuleTest : AbstractKotlinNavigationMultiModuleTest() { override fun doNavigate(editor: Editor, file: PsiFile): GotoTargetHandler.GotoData { - val gotoAction = GotoSuperActionHandler() - val (superDeclarations, _) = gotoAction.allSuperDeclarationsAndDescriptor(editor, file) + val (superDeclarations, _) = GotoSuperActionHandler.SuperDeclarationsAndDescriptor.forDeclarationAtCaret(editor, file) return GotoTargetHandler.GotoData(file.findElementAt(editor.caretModel.offset)!!, superDeclarations.toTypedArray(), emptyList()) }