Uast: making local lambda resolve and methods multiresolve work via resolveToDeclaration and resolveToPsiMethod
also fixes KT-36275
This commit is contained in:
@@ -530,7 +530,7 @@ internal object KotlinConverter {
|
||||
is UastKotlinPsiParameterBase<*> -> el<UParameter> {
|
||||
original.ktOrigin.safeAs<KtTypeReference>()?.let { convertReceiverParameter(it) }
|
||||
}
|
||||
is UastKotlinPsiVariable -> el<UVariable>(buildKt(original.ktElement, ::KotlinUVariable))
|
||||
is UastKotlinPsiVariable -> el<ULocalVariable>(buildKt(original.ktElement, ::KotlinULocalVariable))
|
||||
|
||||
is KtEnumEntry -> el<UEnumConstant> {
|
||||
convertEnumEntry(original, givenParent)
|
||||
|
||||
+10
-20
@@ -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()
|
||||
})
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ internal val KOTLIN_CACHED_UELEMENT_KEY = Key.create<WeakReference<UElement>>("c
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun String?.orAnonymous(kind: String = ""): String = this ?: "<anonymous" + (if (kind.isNotBlank()) " $kind" else "") + ">"
|
||||
|
||||
internal fun DeclarationDescriptor.toSource(): PsiElement? {
|
||||
private fun DeclarationDescriptor.toSource(): PsiElement? {
|
||||
return try {
|
||||
DescriptorToSourceUtils.getEffectiveReferencedDescriptors(this)
|
||||
.asSequence()
|
||||
|
||||
+6
-9
@@ -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<DeclarationDescriptor> =
|
||||
ServiceManager.getService(ktElement.project, KotlinUastResolveProviderService::class.java).getReferenceVariants(ktElement, nameHint)
|
||||
internal fun getReferenceVariants(ktElement: KtExpression, nameHint: String): Sequence<PsiElement> =
|
||||
ServiceManager.getService(ktElement.project, KotlinUastResolveProviderService::class.java)
|
||||
.getReferenceVariants(ktElement, nameHint)
|
||||
.mapNotNull { resolveToDeclaration(ktElement, it) }
|
||||
|
||||
internal fun UElement.getResolveResultVariants(ktExpression: KtExpression?): Iterable<ResolveResult> {
|
||||
internal fun getResolveResultVariants(ktExpression: KtExpression?): Iterable<ResolveResult> {
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user