From f5df64674f9f9823365f1529cd26e8f6e609d941 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Thu, 2 Apr 2020 15:34:42 +0300 Subject: [PATCH] Uast: making local lambda resolve and methods multiresolve work via `resolveToDeclaration` and `resolveToPsiMethod` also fixes KT-36275 --- .../uast/kotlin/KotlinUastLanguagePlugin.kt | 2 +- .../KotlinUFunctionCallExpression.kt | 30 +++++++------------ .../internal/kotlinInternalUastUtils.kt | 2 +- .../kotlin/internal/kotlinUastMultiresolve.kt | 15 ++++------ .../uast-kotlin/tests/KotlinUastApiTest.kt | 4 +-- 5 files changed, 20 insertions(+), 33 deletions(-) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 8ecd0cd3fc4..be24b6c18c5 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -530,7 +530,7 @@ internal object KotlinConverter { is UastKotlinPsiParameterBase<*> -> el { original.ktOrigin.safeAs()?.let { convertReceiverParameter(it) } } - is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) + is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinULocalVariable)) is KtEnumEntry -> el { convertEnumEntry(original, givenParent) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt index eedc2ffbeb9..f8c455d6523 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt @@ -16,23 +16,16 @@ package org.jetbrains.uast.kotlin -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiNamedElement -import com.intellij.psi.PsiType +import com.intellij.psi.* import com.intellij.psi.util.PsiTypesUtil -import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.uast.* import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.kotlin.declarations.KotlinUIdentifier @@ -151,21 +144,17 @@ class KotlinUFunctionCallExpression( } val ktNameReferenceExpression = sourcePsi.calleeExpression as? KtNameReferenceExpression ?: return null - val variableCallDescriptor = - (resolvedCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor - ?: (resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.takeIf { it.visibility == Visibilities.LOCAL } - ?: return null + val localCallableDeclaration = resolveToDeclaration(ktNameReferenceExpression) as? PsiVariable ?: return null + if (localCallableDeclaration !is PsiLocalVariable && localCallableDeclaration !is PsiParameter) return null // an implicit receiver for variables calls (KT-25524) return object : KotlinAbstractUExpression(this), UReferenceExpression { - private val resolvedDeclaration = variableCallDescriptor.toSource() + override val sourcePsi: KtNameReferenceExpression get() = ktNameReferenceExpression - override val psi: KtNameReferenceExpression get() = ktNameReferenceExpression + override val resolvedName: String? get() = localCallableDeclaration.name - override val resolvedName: String? get() = (resolvedDeclaration as? PsiNamedElement)?.name - - override fun resolve(): PsiElement? = resolvedDeclaration + override fun resolve(): PsiElement? = localCallableDeclaration } @@ -177,9 +166,10 @@ class KotlinUFunctionCallExpression( val methodName = methodName ?: calleeExpression.text ?: return emptyList() val variants = getReferenceVariants(calleeExpression, methodName) return variants.flatMap { - when (val source = it.toSource()) { - is KtClass -> source.toLightClass()?.constructors?.asSequence().orEmpty() - else -> resolveToPsiMethod(sourcePsi, it, source)?.let { sequenceOf(it) }.orEmpty() + when (it) { + is PsiClass -> it.constructors.asSequence() + is PsiMethod -> sequenceOf(it) + else -> emptySequence() } }.map { TypedResolveResult(it) }.asIterable() }) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index 0660841746b..876ef40908e 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -89,7 +89,7 @@ internal val KOTLIN_CACHED_UELEMENT_KEY = Key.create>("c @Suppress("NOTHING_TO_INLINE") internal inline fun String?.orAnonymous(kind: String = ""): String = this ?: "" -internal fun DeclarationDescriptor.toSource(): PsiElement? { +private fun DeclarationDescriptor.toSource(): PsiElement? { return try { DescriptorToSourceUtils.getEffectiveReferencedDescriptors(this) .asSequence() diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt index 12813c76076..a80b6640a83 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinUastMultiresolve.kt @@ -11,28 +11,25 @@ import com.intellij.psi.PsiPolyVariantReference import com.intellij.psi.PsiSubstitutor import com.intellij.psi.ResolveResult import com.intellij.psi.infos.CandidateInfo -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.uast.UElement import org.jetbrains.uast.UMultiResolvable import org.jetbrains.uast.UResolvable import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService import org.jetbrains.uast.kotlin.resolveToDeclaration -internal fun getReferenceVariants(ktElement: KtElement, nameHint: String): Sequence = - ServiceManager.getService(ktElement.project, KotlinUastResolveProviderService::class.java).getReferenceVariants(ktElement, nameHint) +internal fun getReferenceVariants(ktElement: KtExpression, nameHint: String): Sequence = + ServiceManager.getService(ktElement.project, KotlinUastResolveProviderService::class.java) + .getReferenceVariants(ktElement, nameHint) + .mapNotNull { resolveToDeclaration(ktElement, it) } -internal fun UElement.getResolveResultVariants(ktExpression: KtExpression?): Iterable { +internal fun getResolveResultVariants(ktExpression: KtExpression?): Iterable { ktExpression ?: return emptyList() val referenceVariants = getReferenceVariants(ktExpression, ktExpression.name ?: ktExpression.text) - fun asCandidateInfo(descriptor: DeclarationDescriptor): CandidateInfo? = - resolveToDeclaration(ktExpression, descriptor)?.let { CandidateInfo(it, PsiSubstitutor.EMPTY) } - - return referenceVariants.mapNotNull(::asCandidateInfo).asIterable() + return referenceVariants.mapNotNull {CandidateInfo(it, PsiSubstitutor.EMPTY) }.asIterable() } diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt index c82193b0fa4..6ce09cf25d9 100644 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt +++ b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt @@ -573,8 +573,8 @@ class KotlinUastApiTest : AbstractKotlinUastTest() { val receiver = localFunction.receiver ?: kfail("receiver expected") assertEquals("UReferenceExpression", receiver.asLogString()) val uVariable = (receiver as UReferenceExpression).resolve().toUElement() ?: kfail("uelement expected") - assertEquals("ULambdaExpression", uVariable.asLogString()) - assertEquals(uVariable, localFunctionResolved.toUElement()) + assertEquals("ULocalVariable (name = bar)", uVariable.asLogString()) + assertEquals((uVariable as ULocalVariable).uastInitializer, localFunctionResolved.toUElement()) } }