FIR/UAST: move multi resolve utils/APIs to the base module/service

This commit is contained in:
Jinseong Jeon
2021-06-08 18:17:37 -07:00
committed by TeamCityServer
parent e870bf7399
commit 77e8aed995
12 changed files with 59 additions and 40 deletions
@@ -19,6 +19,8 @@ interface BaseKotlinUastResolveProviderService {
fun convertParent(uElement: UElement): UElement? fun convertParent(uElement: UElement): UElement?
fun getReferenceVariants(ktExpression: KtExpression, nameHint: String): Sequence<PsiElement>
fun resolveToDeclaration(ktExpression: KtExpression): PsiElement? fun resolveToDeclaration(ktExpression: KtExpression): PsiElement?
fun resolveToType(ktTypeReference: KtTypeReference, source: UElement): PsiType? fun resolveToType(ktTypeReference: KtTypeReference, source: UElement): PsiType?
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.uast.kotlin.internal
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.ResolveResult
import com.intellij.psi.infos.CandidateInfo
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.uast.kotlin.BaseKotlinUastResolveProviderService
fun getResolveResultVariants(
baseKotlinUastResolveProviderService: BaseKotlinUastResolveProviderService,
ktExpression: KtExpression?
): Iterable<ResolveResult> {
ktExpression ?: return emptyList()
val referenceVariants = baseKotlinUastResolveProviderService.getReferenceVariants(ktExpression, ktExpression.name ?: ktExpression.text)
return referenceVariants.mapNotNull { CandidateInfo(it, PsiSubstitutor.EMPTY) }.asIterable()
}
@@ -6,9 +6,14 @@
package org.jetbrains.uast.kotlin.internal package org.jetbrains.uast.kotlin.internal
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.uast.kotlin.FirKotlinUastResolveProviderService import org.jetbrains.uast.kotlin.FirKotlinUastResolveProviderService
class FirCliKotlinUastResolveProviderService : FirKotlinUastResolveProviderService { class FirCliKotlinUastResolveProviderService : FirKotlinUastResolveProviderService {
// Currently, UAST CLI is used by Android Lint, i.e., everything is a JVM element. // Currently, UAST CLI is used by Android Lint, i.e., everything is a JVM element.
override fun isJvmElement(psiElement: PsiElement): Boolean = true override fun isJvmElement(psiElement: PsiElement): Boolean = true
override fun getReferenceVariants(ktExpression: KtExpression, nameHint: String): Sequence<PsiElement> {
return emptySequence() // Not supported (as per the counterpart [CliKotlinUastResolveProviderService])
}
} }
@@ -6,8 +6,13 @@
package org.jetbrains.uast.kotlin.internal package org.jetbrains.uast.kotlin.internal
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.uast.kotlin.FirKotlinUastResolveProviderService import org.jetbrains.uast.kotlin.FirKotlinUastResolveProviderService
class FirIdeaKotlinUastResolveProviderService : FirKotlinUastResolveProviderService { class FirIdeaKotlinUastResolveProviderService : FirKotlinUastResolveProviderService {
override fun isJvmElement(psiElement: PsiElement): Boolean = psiElement.isJvmElement override fun isJvmElement(psiElement: PsiElement): Boolean = psiElement.isJvmElement
override fun getReferenceVariants(ktExpression: KtExpression, nameHint: String): Sequence<PsiElement> {
TODO("Not yet implemented")
}
} }
@@ -9,16 +9,17 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.resolveCandidates import org.jetbrains.kotlin.idea.core.resolveCandidates
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService
import org.jetbrains.uast.kotlin.resolveToDeclarationImpl
class IdeaKotlinUastResolveProviderService : KotlinUastResolveProviderService { class IdeaKotlinUastResolveProviderService : KotlinUastResolveProviderService {
override fun getBindingContext(element: KtElement) = element.analyze(BodyResolveMode.PARTIAL_WITH_CFA) override fun getBindingContext(element: KtElement) = element.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
@@ -37,10 +38,12 @@ class IdeaKotlinUastResolveProviderService : KotlinUastResolveProviderService {
return element.languageVersionSettings return element.languageVersionSettings
} }
override fun getReferenceVariants(ktElement: KtElement, nameHint: String): Sequence<DeclarationDescriptor> { override fun getReferenceVariants(ktExpression: KtExpression, nameHint: String): Sequence<PsiElement> {
val resolutionFacade = ktElement.getResolutionFacade() val resolutionFacade = ktExpression.getResolutionFacade()
val bindingContext = ktElement.analyze() val bindingContext = ktExpression.analyze()
val call = ktElement.getCall(bindingContext) ?: return emptySequence() val call = ktExpression.getCall(bindingContext) ?: return emptySequence()
return call.resolveCandidates(bindingContext, resolutionFacade).map { it.candidateDescriptor }.asSequence() return call.resolveCandidates(bindingContext, resolutionFacade)
.mapNotNull { resolveToDeclarationImpl(ktExpression, it.candidateDescriptor) }
.asSequence()
} }
} }
@@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType import com.intellij.psi.PsiType
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.KtTypeReference
@@ -23,7 +22,6 @@ interface KotlinUastResolveProviderService : BaseKotlinUastResolveProviderServic
fun getBindingContext(element: KtElement): BindingContext fun getBindingContext(element: KtElement): BindingContext
fun getTypeMapper(element: KtElement): KotlinTypeMapper? fun getTypeMapper(element: KtElement): KotlinTypeMapper?
fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings
fun getReferenceVariants(ktElement: KtElement, nameHint: String): Sequence<DeclarationDescriptor>
override val baseKotlinConverter: BaseKotlinConverter override val baseKotlinConverter: BaseKotlinConverter
get() = KotlinConverter get() = KotlinConverter
@@ -25,8 +25,8 @@ import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.internal.getResolveResultVariants import org.jetbrains.uast.kotlin.internal.getResolveResultVariants
class KotlinUCallableReferenceExpression( class KotlinUCallableReferenceExpression(
override val sourcePsi: KtCallableReferenceExpression, override val sourcePsi: KtCallableReferenceExpression,
givenParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UCallableReferenceExpression, UMultiResolvable, KotlinUElementWithType { ) : KotlinAbstractUExpression(givenParent), UCallableReferenceExpression, UMultiResolvable, KotlinUElementWithType {
override val qualifierExpression: UExpression? override val qualifierExpression: UExpression?
get() { get() {
@@ -48,6 +48,7 @@ class KotlinUCallableReferenceExpression(
override fun resolve(): PsiElement? = baseResolveProviderService.resolveToDeclaration(sourcePsi.callableReference) override fun resolve(): PsiElement? = baseResolveProviderService.resolveToDeclaration(sourcePsi.callableReference)
override fun multiResolve(): Iterable<ResolveResult> = getResolveResultVariants(sourcePsi.callableReference) override fun multiResolve(): Iterable<ResolveResult> =
getResolveResultVariants(baseResolveProviderService, sourcePsi.callableReference)
} }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.uast.* import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.kotlin.internal.TypedResolveResult import org.jetbrains.uast.kotlin.internal.TypedResolveResult
import org.jetbrains.uast.kotlin.internal.getReferenceVariants
import org.jetbrains.uast.visitor.UastVisitor import org.jetbrains.uast.visitor.UastVisitor
class KotlinUFunctionCallExpression( class KotlinUFunctionCallExpression(
@@ -164,7 +163,7 @@ class KotlinUFunctionCallExpression(
val contextElement = sourcePsi val contextElement = sourcePsi
val calleeExpression = contextElement.calleeExpression as? KtReferenceExpression ?: return emptyList() val calleeExpression = contextElement.calleeExpression as? KtReferenceExpression ?: return emptyList()
val methodName = methodName ?: calleeExpression.text ?: return emptyList() val methodName = methodName ?: calleeExpression.text ?: return emptyList()
val variants = getReferenceVariants(calleeExpression, methodName) val variants = baseResolveProviderService.getReferenceVariants(calleeExpression, methodName)
return variants.flatMap { return variants.flatMap {
when (it) { when (it) {
is PsiClass -> it.constructors.asSequence() is PsiClass -> it.constructors.asSequence()
@@ -26,10 +26,10 @@ import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.kotlin.internal.getResolveResultVariants import org.jetbrains.uast.kotlin.internal.getResolveResultVariants
class KotlinUSafeQualifiedExpression( class KotlinUSafeQualifiedExpression(
override val sourcePsi: KtSafeQualifiedExpression, override val sourcePsi: KtSafeQualifiedExpression,
givenParent: UElement? givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression, UMultiResolvable, ) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression, UMultiResolvable,
KotlinUElementWithType, KotlinEvaluatableUElement { KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(sourcePsi.receiverExpression, this) } override val receiver by lz { KotlinConverter.convertOrEmpty(sourcePsi.receiverExpression, this) }
override val selector by lz { KotlinConverter.convertOrEmpty(sourcePsi.selectorExpression, this) } override val selector by lz { KotlinConverter.convertOrEmpty(sourcePsi.selectorExpression, this) }
override val accessType = KotlinQualifiedExpressionAccessTypes.SAFE override val accessType = KotlinQualifiedExpressionAccessTypes.SAFE
@@ -38,5 +38,7 @@ class KotlinUSafeQualifiedExpression(
get() = (resolve() as? PsiNamedElement)?.name get() = (resolve() as? PsiNamedElement)?.name
override fun resolve(): PsiElement? = sourcePsi.selectorExpression?.let { baseResolveProviderService.resolveToDeclaration(it) } override fun resolve(): PsiElement? = sourcePsi.selectorExpression?.let { baseResolveProviderService.resolveToDeclaration(it) }
override fun multiResolve(): Iterable<ResolveResult> = getResolveResultVariants(sourcePsi.selectorExpression)
override fun multiResolve(): Iterable<ResolveResult> =
getResolveResultVariants(baseResolveProviderService, sourcePsi.selectorExpression)
} }
@@ -10,10 +10,10 @@ import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
@@ -40,7 +40,7 @@ class CliKotlinUastResolveProviderService : KotlinUastResolveProviderService {
return element.project.analysisCompletedHandler?.getLanguageVersionSettings() ?: LanguageVersionSettingsImpl.DEFAULT return element.project.analysisCompletedHandler?.getLanguageVersionSettings() ?: LanguageVersionSettingsImpl.DEFAULT
} }
override fun getReferenceVariants(ktElement: KtElement, nameHint: String): Sequence<DeclarationDescriptor> = override fun getReferenceVariants(ktExpression: KtExpression, nameHint: String): Sequence<PsiElement> =
emptySequence() // Not supported emptySequence() // Not supported
} }
@@ -308,7 +308,7 @@ internal fun resolveToDeclarationImpl(sourcePsi: KtExpression): PsiElement? =
?.let { descriptor -> resolveToDeclarationImpl(sourcePsi, descriptor) } ?.let { descriptor -> resolveToDeclarationImpl(sourcePsi, descriptor) }
} }
internal fun resolveToDeclarationImpl(sourcePsi: KtExpression, declarationDescriptor: DeclarationDescriptor): PsiElement? { fun resolveToDeclarationImpl(sourcePsi: KtExpression, declarationDescriptor: DeclarationDescriptor): PsiElement? {
declarationDescriptor.toSource()?.getMaybeLightElement(sourcePsi)?.let { return it } declarationDescriptor.toSource()?.getMaybeLightElement(sourcePsi)?.let { return it }
var declarationDescriptor = declarationDescriptor var declarationDescriptor = declarationDescriptor
@@ -5,31 +5,12 @@
package org.jetbrains.uast.kotlin.internal package org.jetbrains.uast.kotlin.internal
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiPolyVariantReference import com.intellij.psi.PsiPolyVariantReference
import com.intellij.psi.PsiSubstitutor import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.ResolveResult import com.intellij.psi.ResolveResult
import com.intellij.psi.infos.CandidateInfo import com.intellij.psi.infos.CandidateInfo
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService
import org.jetbrains.uast.kotlin.resolveToDeclarationImpl
internal fun getReferenceVariants(ktElement: KtExpression, nameHint: String): Sequence<PsiElement> =
ServiceManager.getService(ktElement.project, KotlinUastResolveProviderService::class.java)
.getReferenceVariants(ktElement, nameHint)
.mapNotNull { resolveToDeclarationImpl(ktElement, it) }
internal fun getResolveResultVariants(ktExpression: KtExpression?): Iterable<ResolveResult> {
ktExpression ?: return emptyList()
val referenceVariants = getReferenceVariants(ktExpression, ktExpression.name ?: ktExpression.text)
return referenceVariants.mapNotNull {CandidateInfo(it, PsiSubstitutor.EMPTY) }.asIterable()
}
internal fun KtElement.multiResolveResults(): Sequence<ResolveResult> = internal fun KtElement.multiResolveResults(): Sequence<ResolveResult> =
references.asSequence().flatMap { ref -> references.asSequence().flatMap { ref ->
@@ -43,4 +24,3 @@ class TypedResolveResult<T : PsiElement>(element: T) : CandidateInfo(element, Ps
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun getElement(): T = super.getElement() as T override fun getElement(): T = super.getElement() as T
} }