K2 UAST: lookup declarations with JvmName

^KT-68404 fixed
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisLibraryBinaryDecompiledModulePsiDeclarationProviderTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisLibraryBinaryDecompiledModulePsiDeclarationProviderTestGenerated.java
index d20d942..d78dad8 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisLibraryBinaryDecompiledModulePsiDeclarationProviderTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisLibraryBinaryDecompiledModulePsiDeclarationProviderTestGenerated.java
@@ -52,6 +52,24 @@
   }
 
   @Test
+  @TestMetadata("jvmNameOnFunction.kt")
+  public void testJvmNameOnFunction() {
+    runTest("analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.kt");
+  }
+
+  @Test
+  @TestMetadata("jvmNameOnGetter.kt")
+  public void testJvmNameOnGetter() {
+    runTest("analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.kt");
+  }
+
+  @Test
+  @TestMetadata("jvmNameOnSetter.kt")
+  public void testJvmNameOnSetter() {
+    runTest("analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.kt");
+  }
+
+  @Test
   @TestMetadata("multifileFacade.kt")
   public void testMultifileFacade() {
     runTest("analysis/analysis-api/testData/standalone/binary/multifileFacade.kt");
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisSourceModulePsiDeclarationProviderTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisSourceModulePsiDeclarationProviderTestGenerated.java
index d07e061..88cee27 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisSourceModulePsiDeclarationProviderTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/psiDeclarationProvider/FirStandaloneNormalAnalysisSourceModulePsiDeclarationProviderTestGenerated.java
@@ -58,6 +58,12 @@
   }
 
   @Test
+  @TestMetadata("getJavaClass.kt")
+  public void testGetJavaClass() {
+    runTest("analysis/analysis-api/testData/standalone/source/getJavaClass.kt");
+  }
+
+  @Test
   @TestMetadata("listIterator.kt")
   public void testListIterator() {
     runTest("analysis/analysis-api/testData/standalone/source/listIterator.kt");
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.kt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.kt
new file mode 100644
index 0000000..fd111e8
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.kt
@@ -0,0 +1,19 @@
+// MODULE: lib
+// FILE: Test.kt
+
+package test.pkg
+
+object Test {
+    @JvmName("notFoo")
+    fun foo() {}
+}
+
+// MODULE: app(lib)
+// MODULE_KIND: Source
+// FILE: main.kt
+
+import test.pkg.Test
+
+fun test() {
+    Test.f<caret>oo()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.txt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.txt
new file mode 100644
index 0000000..b212de1
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnFunction.txt
@@ -0,0 +1,2 @@
+Resolved to:
+PsiMethod:notFoo(): PsiType:void
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.kt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.kt
new file mode 100644
index 0000000..32d82fb
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.kt
@@ -0,0 +1,18 @@
+// MODULE: lib
+// FILE: Test.kt
+
+package test.pkg
+
+val Int.prop: Int
+  @JvmName("ownPropGetter")
+  get() = this * 31
+
+// MODULE: app(lib)
+// MODULE_KIND: Source
+// FILE: main.kt
+
+import test.pkg.*
+
+fun test() {
+    42.pro<caret>p
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.txt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.txt
new file mode 100644
index 0000000..2c490f4
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnGetter.txt
@@ -0,0 +1,2 @@
+Resolved to:
+PsiMethod:ownPropGetter(p: PsiType:int): PsiType:int
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.kt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.kt
new file mode 100644
index 0000000..a416fb8
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.kt
@@ -0,0 +1,26 @@
+// MODULE: lib
+// FILE: Test.kt
+
+package test.pkg
+
+class Test(
+    var x: Int
+) {
+}
+
+var Test.ext: Int
+    get() = this.x
+    @JvmName("ownPropSetter")
+    set(value) {
+        this.x = value
+    }
+
+// MODULE: app(lib)
+// MODULE_KIND: Source
+// FILE: main.kt
+
+import test.pkg.*
+
+fun test(t: Test) {
+    t.ex<caret>t = 42
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.txt b/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.txt
new file mode 100644
index 0000000..9de9a3b
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/binary/jvmNameOnSetter.txt
@@ -0,0 +1,2 @@
+Resolved to:
+PsiMethod:getExt(p: PsiType:Test): PsiType:int
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/standalone/source/getJavaClass.kt b/analysis/analysis-api/testData/standalone/source/getJavaClass.kt
new file mode 100644
index 0000000..05bd99b
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/source/getJavaClass.kt
@@ -0,0 +1,7 @@
+// WITH_STDLIB
+
+class Test {
+    fun test() {
+        val x = Test::class.ja<caret>va
+    }
+}
diff --git a/analysis/analysis-api/testData/standalone/source/getJavaClass.txt b/analysis/analysis-api/testData/standalone/source/getJavaClass.txt
new file mode 100644
index 0000000..9459abc
--- /dev/null
+++ b/analysis/analysis-api/testData/standalone/source/getJavaClass.txt
@@ -0,0 +1,2 @@
+Resolved to:
+PsiMethod:getJavaClass(p: PsiType:KClass<T>): PsiType:Class<T>
\ No newline at end of file
diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/DecompiledPsiDeclarationProvider.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/DecompiledPsiDeclarationProvider.kt
index 7a998a2..9b8b230d 100644
--- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/DecompiledPsiDeclarationProvider.kt
+++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/DecompiledPsiDeclarationProvider.kt
@@ -8,6 +8,7 @@
 import com.intellij.openapi.project.Project
 import com.intellij.psi.PsiElement
 import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
 import com.intellij.psi.search.GlobalSearchScope
 import org.jetbrains.kotlin.analysis.api.KaSession
 import org.jetbrains.kotlin.analysis.api.symbols.*
@@ -30,11 +31,17 @@
         project: Project
     ): PsiElement? {
         val classId = constructorSymbol.containingClassId ?: return null
-        val psiClass = project.createPsiDeclarationProvider(constructorSymbol.scope(project))
+        val candidates = project.createPsiDeclarationProvider(constructorSymbol.scope(project))
             ?.getClassesByClassId(classId)
-            ?.firstOrNull() ?: return null
-        return psiClass.constructors.find { psiMethod ->
-            representsTheSameDeclaration(psiMethod, constructorSymbol)
+            ?.firstOrNull()
+            ?.constructors
+            ?: return null
+        return if (candidates.size == 1)
+            candidates.single()
+        else {
+            candidates.find { psiMethod ->
+                representsTheSameDeclaration(psiMethod, constructorSymbol)
+            }
         }
     }
 
@@ -42,32 +49,36 @@
         functionLikeSymbol: KaFunctionLikeSymbol,
         project: Project
     ): PsiElement? {
-        return functionLikeSymbol.callableId?.let {
-            val candidates = project.createPsiDeclarationProvider(functionLikeSymbol.scope(project))
-                ?.getFunctions(it)
-            if (candidates?.size == 1)
-                candidates.single()
-            else
-                candidates?.find { psiMethod ->
-                    representsTheSameDeclaration(psiMethod, functionLikeSymbol)
-                }
-        }
+        val candidates = project.createPsiDeclarationProvider(functionLikeSymbol.scope(project))
+            ?.getFunctions(functionLikeSymbol)
+        return if (candidates?.size == 1)
+            candidates.single()
+        else
+            candidates?.find { psiMethod ->
+                representsTheSameDeclaration(psiMethod, functionLikeSymbol)
+            }
     }
 
-    private fun providePsiForProperty(
+    private fun KaSession.providePsiForProperty(
         variableLikeSymbol: KaVariableLikeSymbol,
         project: Project
     ): PsiElement? {
-        return variableLikeSymbol.callableId?.let {
-            val candidates = project.createPsiDeclarationProvider(variableLikeSymbol.scope(project))
-                ?.getProperties(it)
-            if (candidates?.size == 1)
-                candidates.single()
-            else {
-                // Weigh [PsiField]
-                candidates?.firstOrNull { psiMember -> psiMember is PsiField }
-                    ?: candidates?.firstOrNull()
+        val candidates = project.createPsiDeclarationProvider(variableLikeSymbol.scope(project))
+            ?.getProperties(variableLikeSymbol)
+        if (candidates?.size == 1)
+            return candidates.single()
+        else {
+            // Weigh [PsiField]
+            candidates?.firstOrNull { psiMember -> psiMember is PsiField }?.let { return it }
+            if (variableLikeSymbol is KaPropertySymbol) {
+                val getterSymbol = variableLikeSymbol.getter
+                val setterSymbol = variableLikeSymbol.setter
+                candidates?.filterIsInstance<PsiMethod>()?.firstOrNull { psiMethod ->
+                    (getterSymbol != null && representsTheSameDeclaration(psiMethod, getterSymbol) ||
+                            setterSymbol != null && representsTheSameDeclaration(psiMethod, setterSymbol))
+                }?.let { return it }
             }
+            return candidates?.firstOrNull()
         }
     }
 
diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/KotlinPsiDeclarationProvider.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/KotlinPsiDeclarationProvider.kt
index 4e039b6..7072ce0 100644
--- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/KotlinPsiDeclarationProvider.kt
+++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/KotlinPsiDeclarationProvider.kt
@@ -10,7 +10,8 @@
 import com.intellij.psi.PsiMember
 import com.intellij.psi.PsiMethod
 import com.intellij.psi.search.GlobalSearchScope
-import org.jetbrains.kotlin.name.CallableId
+import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionLikeSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KaVariableLikeSymbol
 import org.jetbrains.kotlin.name.ClassId
 
 /**
@@ -24,8 +25,8 @@
      */
     abstract fun getClassesByClassId(classId: ClassId): Collection<PsiClass>
 
-    abstract fun getProperties(callableId: CallableId): Collection<PsiMember>
-    abstract fun getFunctions(callableId: CallableId): Collection<PsiMethod>
+    abstract fun getProperties(variableLikeSymbol: KaVariableLikeSymbol): Collection<PsiMember>
+    abstract fun getFunctions(functionLikeSymbol: KaFunctionLikeSymbol): Collection<PsiMethod>
 }
 
 abstract class KotlinPsiDeclarationProviderFactory {
diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/PsiDeclarationAndKtSymbolEqualityChecker.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/PsiDeclarationAndKtSymbolEqualityChecker.kt
index dee5f63..4100115 100644
--- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/PsiDeclarationAndKtSymbolEqualityChecker.kt
+++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/PsiDeclarationAndKtSymbolEqualityChecker.kt
@@ -11,10 +11,7 @@
 import com.intellij.psi.PsiType
 import com.intellij.psi.PsiTypes
 import org.jetbrains.kotlin.analysis.api.KaSession
-import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
-import org.jetbrains.kotlin.analysis.api.symbols.KaConstructorSymbol
-import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionLikeSymbol
-import org.jetbrains.kotlin.analysis.api.symbols.receiverType
+import org.jetbrains.kotlin.analysis.api.symbols.*
 import org.jetbrains.kotlin.analysis.api.types.KaType
 import org.jetbrains.kotlin.analysis.api.types.KaTypeMappingMode
 
@@ -43,8 +40,11 @@
     private fun typeParametersMatch(psi: PsiMethod, symbol: KaCallableSymbol): Boolean {
         // PsiMethod for constructor won't have type parameters
         if (symbol is KaConstructorSymbol) return psi.isConstructor
-        if (psi.typeParameters.size != symbol.typeParameters.size) return false
-        psi.typeParameters.zip(symbol.typeParameters) { psiTypeParameter, typeParameterSymbol ->
+        val symbolTypeParameters = symbol.typeParameters.takeIf { it.isNotEmpty() }
+            ?: symbol.receiverParameter?.owningCallableSymbol?.typeParameters
+            ?: emptyList()
+        if (psi.typeParameters.size != symbolTypeParameters.size) return false
+        psi.typeParameters.zip(symbolTypeParameters) { psiTypeParameter, typeParameterSymbol ->
             if (psiTypeParameter.name != typeParameterSymbol.name.asString()) return false
             // TODO: type parameter bounds comparison
         }
@@ -52,13 +52,17 @@
     }
 
     private fun KaSession.valueParametersMatch(psi: PsiMethod, symbol: KaFunctionLikeSymbol): Boolean {
-        val valueParameterCount = if (symbol.isExtension) symbol.valueParameters.size + 1 else symbol.valueParameters.size
+        val isExtension = when (symbol) {
+            is KaPropertyAccessorSymbol -> symbol.receiverParameter != null
+            else -> symbol.isExtension
+        }
+        val valueParameterCount = if (isExtension) symbol.valueParameters.size + 1 else symbol.valueParameters.size
         if (psi.parameterList.parametersCount != valueParameterCount) return false
-        if (symbol.isExtension) {
+        if (isExtension) {
             val psiParameter = psi.parameterList.parameters[0]
             if (symbol.receiverType?.let { isTheSameTypes(psi, psiParameter.type, it) } != true) return false
         }
-        val offset = if (symbol.isExtension) 1 else 0
+        val offset = if (isExtension) 1 else 0
         symbol.valueParameters.forEachIndexed { index, valueParameterSymbol ->
             val psiParameter = psi.parameterList.parameters[index + offset]
             // The type of `vararg` value param at last v.s. non-last is mapped differently:
diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticPsiDeclarationFromBinaryModuleProvider.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticPsiDeclarationFromBinaryModuleProvider.kt
index cf4cbfb..1c4b39a 100644
--- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticPsiDeclarationFromBinaryModuleProvider.kt
+++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticPsiDeclarationFromBinaryModuleProvider.kt
@@ -9,13 +9,18 @@
 import com.intellij.psi.*
 import com.intellij.psi.impl.file.impl.JavaFileManager
 import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.api.annotations.toFilter
+import org.jetbrains.kotlin.analysis.api.symbols.*
 import org.jetbrains.kotlin.analysis.providers.KotlinPsiDeclarationProvider
 import org.jetbrains.kotlin.analysis.providers.KotlinPsiDeclarationProviderFactory
 import org.jetbrains.kotlin.analysis.providers.createPackagePartProvider
 import org.jetbrains.kotlin.asJava.classes.lazyPub
 import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_GETTER
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.PROPERTY_SETTER
+import org.jetbrains.kotlin.light.classes.symbol.annotations.getJvmNameFromAnnotation
+import org.jetbrains.kotlin.light.classes.symbol.annotations.toOptionalFilter
 import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
-import org.jetbrains.kotlin.name.CallableId
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.name.Name
@@ -65,13 +70,23 @@
         return listOfNotNull(javaFileManager.findClass(classId.asFqNameString(), scope))
     }
 
-    override fun getProperties(callableId: CallableId): Collection<PsiMember> {
+    override fun getProperties(variableLikeSymbol: KaVariableLikeSymbol): Collection<PsiMember> {
+        val callableId = variableLikeSymbol.callableId ?: return emptyList()
         val classes = callableId.classId?.let { classId ->
             val classFromCurrentClassId = getClassesByClassId(classId)
             // property in companion object is actually materialized at the containing class.
             val classFromOuterClassID = classId.outerClassId?.let { getClassesByClassId(it) } ?: emptyList()
             classFromCurrentClassId + classFromOuterClassID
         } ?: getClassesInPackage(callableId.packageName)
+        if (classes.isEmpty()) return emptyList()
+
+        val propertySymbol = variableLikeSymbol as? KtPropertySymbol
+        val getterJvmName =
+            propertySymbol?.getter?.getJvmNameFromAnnotation(PROPERTY_GETTER.toOptionalFilter())
+                ?: propertySymbol?.getJvmNameFromAnnotation(PROPERTY_GETTER.toFilter())
+        val setterJvmName =
+            propertySymbol?.setter?.getJvmNameFromAnnotation(PROPERTY_SETTER.toOptionalFilter())
+                ?: propertySymbol?.getJvmNameFromAnnotation(PROPERTY_SETTER.toFilter())
         return classes.flatMap { psiClass ->
             psiClass.children
                 .filterIsInstance<PsiMember>()
@@ -82,6 +97,7 @@
                     // PsiField a.k.a. backing field
                     if (name == id) return@filter true
                     // PsiMethod, i.e., accessors
+                    if (name == getterJvmName || name == setterJvmName) return@filter true
                     val nameWithoutPrefix = name.nameWithoutAccessorPrefix ?: return@filter false
                     // E.g., getJVM_FIELD -> JVM_FIELD
                     nameWithoutPrefix == id ||
@@ -102,11 +118,25 @@
             else -> null
         }
 
-    override fun getFunctions(callableId: CallableId): Collection<PsiMethod> {
+    override fun getFunctions(functionLikeSymbol: KaFunctionLikeSymbol): Collection<PsiMethod> {
+        val callableId = functionLikeSymbol.callableId ?: return emptyList()
         val classes = callableId.classId?.let { classId ->
             getClassesByClassId(classId)
         } ?: getClassesInPackage(callableId.packageName)
-        val id = callableId.callableName.identifier
+        if (classes.isEmpty()) return emptyList()
+
+        val jvmName = when (functionLikeSymbol) {
+            is KtPropertyGetterSymbol -> {
+                functionLikeSymbol.getJvmNameFromAnnotation(PROPERTY_GETTER.toOptionalFilter())
+            }
+            is KtPropertySetterSymbol -> {
+                functionLikeSymbol.getJvmNameFromAnnotation(PROPERTY_SETTER.toOptionalFilter())
+            }
+            else -> {
+                functionLikeSymbol.getJvmNameFromAnnotation()
+            }
+        }
+        val id = jvmName ?: callableId.callableName.identifier
         return classes.flatMap { psiClass ->
             psiClass.methods.filter { psiMethod ->
                 psiMethod.name == id ||