From 64a375ccb247fe9bbce4e15eba1177b147efbebe Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 13 Sep 2024 15:47:58 +0200 Subject: [PATCH] [kotlin] fix copy reference on reference ^KTIJ-31304 fixed GitOrigin-RevId: 1a94841d748ce97267b64b6d45cc3b432864329f --- .../idea/KotlinQualifiedNameProvider.kt | 10 +- .../idea/fir/actions/QualifiedNamesTest.kt | 114 ++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 plugins/kotlin/fir/tests/test/org/jetbrains/kotlin/idea/fir/actions/QualifiedNamesTest.kt diff --git a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/KotlinQualifiedNameProvider.kt b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/KotlinQualifiedNameProvider.kt index 7e21938bf938..b20cb93ce756 100644 --- a/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/KotlinQualifiedNameProvider.kt +++ b/plugins/kotlin/base/code-insight/src/org/jetbrains/kotlin/idea/KotlinQualifiedNameProvider.kt @@ -4,12 +4,15 @@ package org.jetbrains.kotlin.idea import com.intellij.ide.actions.JavaQualifiedNameProvider import com.intellij.ide.actions.QualifiedNameProvider +import com.intellij.ide.actions.QualifiedNameProviderUtil import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.asJava.LightClassUtil +import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.psi.KtProperty class KotlinQualifiedNameProvider : QualifiedNameProvider { @@ -17,13 +20,16 @@ class KotlinQualifiedNameProvider : QualifiedNameProvider { override fun getQualifiedName(element: PsiElement) = when (element) { is KtClassOrObject -> element.fqName?.asString() - is KtNamedFunction -> getJavaQualifiedName(LightClassUtil.getLightClassMethod(element)) + is KtFunction -> getJavaQualifiedName(LightClassUtil.getLightClassMethod(element)) is KtProperty -> { val lightClassPropertyMethods = LightClassUtil.getLightClassPropertyMethods(element) val lightElement: PsiElement? = lightClassPropertyMethods.getter ?: lightClassPropertyMethods.backingField getJavaQualifiedName(lightElement) } + is KtNameReferenceExpression -> element.mainReference.resolve()?.let { + QualifiedNameProviderUtil.getQualifiedName(it) + } else -> null } diff --git a/plugins/kotlin/fir/tests/test/org/jetbrains/kotlin/idea/fir/actions/QualifiedNamesTest.kt b/plugins/kotlin/fir/tests/test/org/jetbrains/kotlin/idea/fir/actions/QualifiedNamesTest.kt new file mode 100644 index 000000000000..c406fa1c24f2 --- /dev/null +++ b/plugins/kotlin/fir/tests/test/org/jetbrains/kotlin/idea/fir/actions/QualifiedNamesTest.kt @@ -0,0 +1,114 @@ +// Copyright 2000-2022 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. +package org.jetbrains.kotlin.idea.fir.actions + +import com.intellij.ide.actions.CopyReferenceAction +import com.intellij.ide.actions.QualifiedNameProviderUtil +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.psi.KtVisitorVoid +import org.junit.internal.runners.JUnit38ClassRunner +import org.junit.runner.RunWith + +@RunWith(JUnit38ClassRunner::class) +class QualifiedNamesTest : KotlinLightCodeInsightFixtureTestCase() { + + override val pluginMode: KotlinPluginMode = KotlinPluginMode.K2 + + fun testClassRef() { + myFixture.configureByText( + "class.kt", + """ + package foo.bar + + class Klass { + class Nested + + companion object { + } + } + + object Object { + } + + val anonymous = object { + } + """.trimIndent() + ) + assertEquals( + listOf( + "foo.bar.Klass", + "foo.bar.Klass.Nested", + "foo.bar.Klass.Companion", + "foo.bar.Object", + "foo.bar.ClassKt#getAnonymous", + null + ), + getQualifiedNamesForDeclarations() + ) + } + + fun testOnClassRef() { + val file = myFixture.configureByText( + "Klass.kt", + """ + package foo.bar + + class Klass {} + + fun m() = Klass() + """.trimIndent() + ) + val element = file.findElementAt(myFixture.caretOffset)?.parent ?: error("Cannot find reference at caret") + assertEquals("foo.bar.Klass", QualifiedNameProviderUtil.getQualifiedName(element)) + } + + fun testFunRef() { + myFixture.configureByText( + "fun.kt", + """ + package foo.bar + + class Klass { + fun memberFun() { + } + + val memberVal = ":)" + } + + fun topLevelFun() + + val topLevelVal = ":)" + """.trimIndent() + ) + assertEquals( + listOf( + "foo.bar.Klass", + "foo.bar.Klass#memberFun", + "foo.bar.Klass#getMemberVal", + "foo.bar.FunKt#topLevelFun", + "foo.bar.FunKt#getTopLevelVal" + ), + getQualifiedNamesForDeclarations() + ) + } + + + + + private fun getQualifiedNamesForDeclarations(): List { + val result = ArrayList() + file.accept(object : KtVisitorVoid() { + override fun visitElement(element: PsiElement) { + element.acceptChildren(this) + } + + override fun visitNamedDeclaration(declaration: KtNamedDeclaration) { + result.add(CopyReferenceAction.elementToFqn(declaration)) + super.visitNamedDeclaration(declaration) + } + }) + return result + } +}