[kotlin] go to super: add correct title for classes and properties

^KTIJ-22273 Fixed

GitOrigin-RevId: 987678e869ed70fcfbf0ed0ddf3632f113ff4386
This commit is contained in:
Dmitry Gridin
2022-07-21 12:10:31 +00:00
committed by intellij-monorepo-bot
parent 5e1fade9d2
commit b8416b3684
6 changed files with 164 additions and 55 deletions
@@ -30,8 +30,8 @@ action.text.merge.identical.stacktraces=Merge Identical Stacktraces
action.text.show.methods.to.implement=Show methods to implement
action.text.show.quick.list=Show Quick List
action.text.unmark.generated.0=Unmark Generated {0}
action.GotoSuperClass.text=Go to S_uper Class
action.GotoSuperClass.MainMenu.text=S_uper Class
action.GotoSuperClass.text=Go to S_uper Class or Interface
action.GotoSuperClass.MainMenu.text=S_uper Class or Interface
action.GotoSuperClass.description=Navigate to the declaration of a class that the current class extends or implements
add.to.permits.list.family.name=Add class to permits list
add.to.permits.list=Add ''{0}'' to permits list of a sealed class ''{1}''
@@ -223,6 +223,10 @@ goto.super.chooser.function.title=Choose super function
goto.super.chooser.property.title=Choose super property
goto.super.chooser.class.title=Choose super class or interface
action.GotoSuperProperty.text=Go to S_uper Property
action.GotoSuperProperty.MainMenu.text=S_uper Property
action.GotoSuperProperty.description=Navigate to the declaration of a property that the current property overrides or implements
inspection.unused.receiver.parameter=Receiver parameter is never used
fix.unused.receiver.parameter.remove=Remove redundant receiver parameter
@@ -1,18 +1,23 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.codeInsight.generation.actions.PresentableCodeInsightActionHandler
import com.intellij.codeInsight.navigation.NavigationUtil
import com.intellij.codeInsight.navigation.actions.GotoSuperAction
import com.intellij.featureStatistics.FeatureUsageTracker
import com.intellij.ide.util.EditSourceUtil
import com.intellij.idea.ActionsBundle
import com.intellij.java.JavaBundle
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.Presentation
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtilCore
import com.intellij.psi.util.findParentOfType
import org.jetbrains.annotations.Nls
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -23,7 +28,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.search.declarationsSearch.findSuperDescriptors
import org.jetbrains.kotlin.psi.*
class GotoSuperActionHandler : CodeInsightActionHandler {
class GotoSuperActionHandler : PresentableCodeInsightActionHandler {
data class SuperDeclarationsAndDescriptor(val supers: List<PsiElement>, val descriptor: DeclarationDescriptor?) {
constructor() : this(emptyList(), null)
@@ -74,14 +79,50 @@ class GotoSuperActionHandler : CodeInsightActionHandler {
}
}
@Nls
private fun getTitle(descriptor: DeclarationDescriptor): String? =
when (descriptor) {
is ClassDescriptor -> KotlinBundle.message("goto.super.chooser.class.title")
is PropertyDescriptor -> KotlinBundle.message("goto.super.chooser.property.title")
is SimpleFunctionDescriptor -> KotlinBundle.message("goto.super.chooser.function.title")
else -> null
override fun update(editor: Editor, file: PsiFile, presentation: Presentation?) {
update(editor, file, presentation, null)
}
override fun update(editor: Editor, file: PsiFile, presentation: Presentation?, actionPlace: String?) {
if (presentation == null) return
val containingElement = file.findElementAt(editor.caretModel.offset)?.findParentOfType<KtDeclaration>()
val useShortName = actionPlace != null && (ActionPlaces.MAIN_MENU == actionPlace || ActionPlaces.isPopupPlace(actionPlace))
when (containingElement) {
is KtClassOrObject -> {
presentation.text = JavaBundle.message(
if (useShortName) "action.GotoSuperClass.MainMenu.text" else "action.GotoSuperClass.text"
)
presentation.description = JavaBundle.message("action.GotoSuperClass.description")
}
is KtProperty -> {
presentation.text = KotlinBundle.message(
if (useShortName) "action.GotoSuperProperty.MainMenu.text" else "action.GotoSuperProperty.text"
)
presentation.description = KotlinBundle.message("action.GotoSuperProperty.description")
}
else -> {
presentation.text = ActionsBundle.actionText(
if (useShortName) "GotoSuperMethod.MainMenu" else "GotoSuperMethod"
)
presentation.description = ActionsBundle.actionDescription("GotoSuperMethod")
}
}
}
@Nls
private fun getTitle(descriptor: DeclarationDescriptor): String? = when (descriptor) {
is ClassDescriptor -> KotlinBundle.message("goto.super.chooser.class.title")
is PropertyDescriptor -> KotlinBundle.message("goto.super.chooser.property.title")
is SimpleFunctionDescriptor -> KotlinBundle.message("goto.super.chooser.function.title")
else -> null
}
override fun startInWriteAction() = false
}
@@ -0,0 +1,60 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.searcheverywhere
import com.intellij.ide.actions.searcheverywhere.PSIPresentationBgRendererWrapper
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereManagerImpl
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.ide.util.gotoByName.GotoActionModel
import com.intellij.java.navigation.ChooseByNameTest
import com.intellij.java.navigation.SearchEverywhereTest
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiElement
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.UsefulTestCase
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
abstract class KotlinSearchEverywhereTestCase : LightJavaCodeInsightFixtureTestCase() {
protected fun findPsiByPattern(pattern: String, action: (List<PsiElement>) -> Unit) {
findByPattern(pattern) {
action(it.mapNotNull(PSIPresentationBgRendererWrapper::toPsi))
}
}
protected fun findByPattern(pattern: String, action: (List<Any>) -> Unit) {
val disposable = Disposer.newDisposable("ui disposer")
try {
val event = ChooseByNameTest.createEvent(project)
val ui = SearchEverywhereUI(
project,
SearchEverywhereContributor.EP_NAME.extensionList.map {
val contributor = it.createContributor(event)
Disposer.register(disposable, contributor)
contributor
}
)
Disposer.register(disposable, ui)
ui.switchToTab(SearchEverywhereManagerImpl.ALL_CONTRIBUTORS_GROUP_ID)
val future = ui.findElementsForPattern(pattern)
action(
PlatformTestUtil.waitForFuture(future, SearchEverywhereTest.getSEARCH_TIMEOUT().toLong())
)
} finally {
Disposer.dispose(disposable)
}
}
protected fun configureAndCheckActions(text: String, expected: List<String>, pattern: String) {
myFixture.configureByText("TestFile.kt", text)
findByPattern(pattern) { elements ->
val actions = elements.filterIsInstance<GotoActionModel.MatchedValue>()
.map { it.value }
.filterIsInstance<GotoActionModel.ActionWrapper>()
val presentationTexts = actions.map { it.presentation.text }
UsefulTestCase.assertContainsElements(presentationTexts, expected)
}
}
}
@@ -1,35 +1,24 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.searcheverywhere
import com.intellij.ide.actions.searcheverywhere.PSIPresentationBgRendererWrapper
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereManagerImpl
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.java.navigation.ChooseByNameTest
import com.intellij.java.navigation.SearchEverywhereTest
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiElement
import com.intellij.psi.util.parentOfType
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.keysToMap
/**
* @see KtSearchEverywhereEqualityProvider
*/
class NativePsiAndKtLightElementEqualityProviderTest : LightJavaCodeInsightFixtureTestCase() {
class NativePsiAndKtLightElementEqualityProviderTest : KotlinSearchEverywhereTestCase() {
fun `test only class presented`() {
val file = myFixture.configureByText("MyKotlinClassWithStrangeName.kt", "class MyKotlinClassWithStrangeName")
val klass = file.findElementAt(myFixture.caretOffset)?.parentOfType<KtClass>()!!
val ulc = LightClassGenerationSupport.getInstance(project).createUltraLightClass(klass)!!
findByPattern("MyKotlinClassWithStrangeName") { results ->
findPsiByPattern("MyKotlinClassWithStrangeName") { results ->
assertTrue(klass in results)
assertFalse(file in results)
assertFalse(ulc in results)
@@ -46,7 +35,7 @@ class NativePsiAndKtLightElementEqualityProviderTest : LightJavaCodeInsightFixtu
val klass2 = file.declarations.last() as KtClass
val ulc = LightClassGenerationSupport.getInstance(project).createUltraLightClass(klass)!!
val ulc2 = LightClassGenerationSupport.getInstance(project).createUltraLightClass(klass2)!!
findByPattern("MyKotlinClassWithStrangeName") { results ->
findPsiByPattern("MyKotlinClassWithStrangeName") { results ->
assertTrue(klass in results)
assertTrue(klass2 in results)
assertFalse(file in results)
@@ -64,7 +53,7 @@ class NativePsiAndKtLightElementEqualityProviderTest : LightJavaCodeInsightFixtu
val klass = file.findElementAt(myFixture.caretOffset)?.parentOfType<KtClass>()!!
val ulc = LightClassGenerationSupport.getInstance(project).createUltraLightClass(klass)!!
val syntheticClass = file.declarations.last().cast<KtNamedFunction>().toLightMethods().single().parent
findByPattern("MyKotlinClassWithStrangeName") { results ->
findPsiByPattern("MyKotlinClassWithStrangeName") { results ->
assertTrue(results.toString(), results.size == 1)
assertTrue(klass in results)
assertFalse(file in results)
@@ -72,31 +61,4 @@ class NativePsiAndKtLightElementEqualityProviderTest : LightJavaCodeInsightFixtu
assertFalse(ulc in results)
}
}
private fun findByPattern(pattern: String, action: (List<PsiElement>) -> Unit) {
val disposable = Disposer.newDisposable("ui disposer")
try {
val event = ChooseByNameTest.createEvent(project)
val ui = SearchEverywhereUI(
project,
SearchEverywhereContributor.EP_NAME.extensionList.map {
val contributor = it.createContributor(event)
Disposer.register(disposable, contributor)
contributor
}
)
Disposer.register(disposable, ui)
ui.switchToTab(SearchEverywhereManagerImpl.ALL_CONTRIBUTORS_GROUP_ID)
val future = ui.findElementsForPattern(pattern)
action(
PlatformTestUtil.waitForFuture(future, SearchEverywhereTest.getSEARCH_TIMEOUT().toLong()).mapNotNull {
PSIPresentationBgRendererWrapper.toPsi(it)
}
)
} finally {
Disposer.dispose(disposable)
}
}
}
@@ -0,0 +1,42 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.searcheverywhere
class SuperSymbolTests : KotlinSearchEverywhereTestCase() {
fun `test super class`(): Unit = doTest(
text = """
open class A
class B<caret> : A()
""".trimIndent(),
action = "Go to Super Class or Interface",
)
fun `test super function`(): Unit = doTest(
text = """
abstract class A {
abstract fun foo()
}
class B : A() {
override fun f<caret>oo() = Unit
}
""".trimIndent(),
action = "Go to Super Method",
)
fun `test super property`(): Unit = doTest(
text = """
abstract class A {
abstract val a: Int
}
class B : A() {
override val a<caret>: Int = 5
}
""".trimIndent(),
action = "Go to Super Property",
)
private fun doTest(text: String, action: String): Unit = configureAndCheckActions(
text = text,
expected = listOf(action),
pattern = "go to super",
)
}