[Analysis API] Make a separate module for kt-reference-fe10

This commit is contained in:
Tianyu Geng
2022-05-06 20:32:08 +00:00
committed by Ilya Kirillov
parent 19e9143bc1
commit 010431e9e7
21 changed files with 42 additions and 22 deletions
+1 -1
View File
@@ -10,12 +10,12 @@ dependencies {
implementation(project(":analysis:analysis-api-impl-base"))
implementation(project(":analysis:analysis-internal-utils"))
implementation(project(":analysis:kt-references"))
implementation(project(":analysis:kt-references:kt-references-fe10"))
implementation(project(":compiler:backend"))
implementation(project(":compiler:backend.jvm"))
implementation(project(":compiler:backend-common"))
implementation(project(":compiler:backend.common.jvm"))
implementation(project(":compiler:light-classes"))
testApiJUnit5()
testImplementation(project(":analysis:analysis-api-providers"))
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2022 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10ReferenceResolutionHelper
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KDocReference
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
class Fe10KDocReference(element: KDocName) : KDocReference(element), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> =
KtFe10ReferenceResolutionHelper.getInstance().resolveKDocLink(element)
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2022 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.kotlin.analysis.api.descriptors.references
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.util.SmartList
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.asJava.canHaveSyntheticGetter
import org.jetbrains.kotlin.asJava.canHaveSyntheticSetter
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.utils.addIfNotNull
class Fe10SyntheticPropertyAccessorReference(
expression: KtNameReferenceExpression,
getter: Boolean
) : SyntheticPropertyAccessorReference(expression, getter), KtFe10Reference {
override fun canBeReferenceTo(candidateTarget: PsiElement): Boolean {
if (candidateTarget !is PsiMethod || !isAccessorName(candidateTarget.name)) return false
if (getter && !candidateTarget.canHaveSyntheticGetter || !getter && !candidateTarget.canHaveSyntheticSetter) return false
if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false
return true
}
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val descriptors = expression.getReferenceTargets(context)
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
val result = SmartList<FunctionDescriptor>()
for (descriptor in descriptors) {
if (descriptor is SyntheticJavaPropertyDescriptor) {
if (getter) {
result.add(descriptor.getMethod)
} else {
result.addIfNotNull(descriptor.setMethod)
}
}
}
return result
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
override val resolvesByNames: Collection<Name>
get() = listOf(element.getReferencedNameAsName())
}
@@ -1,26 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtArrayAccessReference
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
class KtFe10ArrayAccessReference(expression: KtArrayAccessExpression) : KtArrayAccessReference(expression), KtFe10Reference {
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val getFunctionDescriptor = context[BindingContext.INDEXED_LVALUE_GET, expression]?.candidateDescriptor
val setFunctionDescriptor = context[BindingContext.INDEXED_LVALUE_SET, expression]?.candidateDescriptor
return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor)
}
}
@@ -1,26 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtCollectionLiteralReference
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
class KtFe10CollectionLiteralReference(
expression: KtCollectionLiteralExpression
) : KtCollectionLiteralReference(expression), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
return listOfNotNull(resolvedCall?.resultingDescriptor)
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,23 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.idea.references.KtConstructorDelegationReference
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
class KtFe10ConstructorDelegationReference(
expression: KtConstructorDelegationReferenceExpression
) : KtConstructorDelegationReference(expression), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,46 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10ReferenceResolutionHelper
import org.jetbrains.kotlin.analysis.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
class KtFe10DestructuringDeclarationEntry(
element: KtDestructuringDeclarationEntry
) : KtDestructuringDeclarationReference(element), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return listOfNotNull(
context[BindingContext.VARIABLE, element],
context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor
)
}
override fun resolve() = multiResolve(false).asSequence()
.map { it.element }
.firstOrNull { it is KtDestructuringDeclarationEntry }
override fun getRangeInElement() = TextRange(0, element.textLength)
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun canRename(): Boolean {
val bindingContext = KtFe10ReferenceResolutionHelper.getInstance().partialAnalyze(element) //TODO: should it use full body resolve?
return resolveToDescriptors(bindingContext).all {
it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
}
}
}
@@ -1,33 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtForLoopInReference
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
class KtFe10ForLoopInReference(expression: KtForExpression) : KtForLoopInReference(expression), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val loopRange = expression.loopRange ?: return emptyList()
return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor }
}
companion object {
private val LOOP_RANGE_KEYS = arrayOf(
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
)
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,37 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.getCall
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
class KtFe10InvokeFunctionReference(expression: KtCallExpression) : KtInvokeFunctionReference(expression), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val call = element.getCall(context)
val resolvedCall = call.getResolvedCall(context)
return when {
resolvedCall is VariableAsFunctionResolvedCall ->
setOf<DeclarationDescriptor>((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor)
call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE ->
setOf<DeclarationDescriptor>(resolvedCall.candidateDescriptor)
else ->
emptyList()
}
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,35 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.descriptors.accessors
import org.jetbrains.kotlin.idea.references.KtPropertyDelegationMethodsReference
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
class KtFe10PropertyDelegationMethodsReference(
expression: KtPropertyDelegate
) : KtPropertyDelegationMethodsReference(expression), KtFe10Reference {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val property = expression.getStrictParentOfType<KtProperty>() ?: return emptyList()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors
?: return emptyList()
return descriptor.accessors.mapNotNull { accessor ->
context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor
} + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor)
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
}
@@ -1,85 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references
import com.intellij.psi.PsiElement
import com.intellij.util.SmartList
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10ReferenceResolutionHelper
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
class KtFe10SimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleNameReference(expression), KtFe10Reference {
override fun canBeReferenceTo(candidateTarget: PsiElement): Boolean {
return element.containingFile == candidateTarget.containingFile ||
KtFe10ReferenceResolutionHelper.getInstance().isInProjectOrLibSource(element, includeScriptsOutsideSourceRoots = true)
}
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
}
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return SmartList<DeclarationDescriptor>().apply {
// Replace Java property with its accessor(s)
for (descriptor in expression.getReferenceTargets(context)) {
val sizeBefore = size
if (descriptor !is JavaPropertyDescriptor) {
add(descriptor)
continue
}
val readWriteAccess = expression.readWriteAccess(true)
descriptor.getter?.let {
if (readWriteAccess.isRead) add(it)
}
descriptor.setter?.let {
if (readWriteAccess.isWrite) add(it)
}
if (size == sizeBefore) {
add(descriptor)
}
}
}
}
override fun isReferenceToViaExtension(element: PsiElement): Boolean {
for (extension in element.project.extensionArea.getExtensionPoint(SimpleNameReferenceExtension.EP_NAME).extensions) {
if (extension.isReferenceTo(this, element)) return true
}
return false
}
override fun getImportAlias(): KtImportAlias? {
fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this
val name = element.getReferencedName()
val file = element.containingKtFile
val importDirective = file.findImportByAlias(name) ?: return null
val fqName = importDirective.importedFqName ?: return null
val helper = KtFe10ReferenceResolutionHelper.getInstance()
val importedDescriptors = helper.resolveImportReference(file, fqName).map { it.unwrap() }
if (getTargetDescriptors(helper.partialAnalyze(element)).any {
it.unwrap().getImportableDescriptor() in importedDescriptors
}) {
return importDirective.alias
}
return null
}
}
@@ -1,63 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references.base
import com.intellij.psi.PsiReference
import org.jetbrains.kotlin.analysis.api.descriptors.references.*
import org.jetbrains.kotlin.idea.references.KotlinPsiReferenceRegistrar
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
import org.jetbrains.kotlin.idea.references.KtDefaultAnnotationArgumentReference
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
class KtFe10KotlinReferenceProviderContributor : KotlinReferenceProviderContributor {
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
with(registrar) {
registerProvider(factory = ::KtFe10SimpleNameReference)
registerProvider(factory = ::KtFe10ForLoopInReference)
registerProvider(factory = ::KtFe10InvokeFunctionReference)
registerProvider(factory = ::KtFe10PropertyDelegationMethodsReference)
registerProvider(factory = ::KtFe10DestructuringDeclarationEntry)
registerProvider(factory = ::KtFe10ArrayAccessReference)
registerProvider(factory = ::KtFe10ConstructorDelegationReference)
registerProvider(factory = ::KtFe10CollectionLiteralReference)
registerProvider(factory = ::Fe10KDocReference)
registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression ->
if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) {
return@registerMultiProvider PsiReference.EMPTY_ARRAY
}
if (nameReferenceExpression.parents.any { it is KtImportDirective || it is KtPackageDirective || it is KtUserType }) {
return@registerMultiProvider PsiReference.EMPTY_ARRAY
}
when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) {
ReferenceAccess.READ ->
arrayOf(Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = true))
ReferenceAccess.WRITE ->
arrayOf(Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = false))
ReferenceAccess.READ_WRITE ->
arrayOf(
Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = true),
Fe10SyntheticPropertyAccessorReference(nameReferenceExpression, getter = false)
)
}
}
registerProvider<KtValueArgument> provider@{ element: KtValueArgument ->
if (element.isNamed()) return@provider null
val annotationEntry = element.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@provider null
if (annotationEntry.valueArguments.size != 1) return@provider null
KtDefaultAnnotationArgumentReference(element)
}
}
}
}
@@ -1,76 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references.base
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import org.jetbrains.kotlin.analysis.api.descriptors.utils.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.idea.references.AbstractKtReference
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import java.util.*
object KtFe10PolyVariantResolver : ResolveCache.PolyVariantResolver<KtReference> {
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
private fun resolveToPsiElements(ref: KtFe10Reference): Collection<PsiElement> {
require(ref is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${ref::class}" }
val bindingContext = KtFe10ReferenceResolutionHelper.getInstance().partialAnalyze(ref.expression)
if (bindingContext == BindingContext.EMPTY) return emptySet()
return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext))
}
private fun resolveToPsiElements(
ref: KtFe10Reference,
context: BindingContext,
targetDescriptors: Collection<DeclarationDescriptor>
): Collection<PsiElement> {
if (targetDescriptors.isNotEmpty()) {
return targetDescriptors.flatMap { target -> resolveToPsiElements(ref, target) }.toSet()
}
val labelTargets = getLabelTargets(ref, context)
if (labelTargets != null) {
return labelTargets
}
return Collections.emptySet()
}
private fun resolveToPsiElements(
ref: KtFe10Reference,
targetDescriptor: DeclarationDescriptor
): Collection<PsiElement> = if (targetDescriptor is PackageViewDescriptor) {
val psiFacade = JavaPsiFacade.getInstance(ref.element.project)
val fqName = targetDescriptor.fqName.asString()
listOfNotNull(psiFacade.findPackage(fqName))
} else {
DescriptorToSourceUtilsIde.getAllDeclarations(ref.element.project, targetDescriptor, ref.element.resolveScope)
}
private fun getLabelTargets(ref: KtFe10Reference, context: BindingContext): Collection<PsiElement>? {
val reference = ref.element as? KtReferenceExpression ?: return null
val labelTarget = context[BindingContext.LABEL_TARGET, reference]
if (labelTarget != null) {
return listOf(labelTarget)
}
return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference]
}
// TODO: Old impl from IDE side has this logic wrapped inside runWithCancellationCheck. Figure out what we should do here.
override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
require(ref is KtFe10Reference) { "reference should be KtFe10Reference, but was ${ref::class}" }
val resolveToPsiElements = resolveToPsiElements(ref)
return resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
}
}
@@ -1,61 +0,0 @@
/*
* 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.kotlin.analysis.api.descriptors.references.base
import com.intellij.psi.PsiMethod
import com.intellij.psi.impl.source.resolve.ResolveCache
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.KtSymbolBasedReference
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.unwrappedTargets
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtImportAlias
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.resolve.BindingContext
interface KtFe10Reference : KtReference, KtSymbolBasedReference {
override val resolver: ResolveCache.PolyVariantResolver<KtReference>
get() = KtFe10PolyVariantResolver
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> = getTargetDescriptors(bindingContext)
fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
val importDirective = alias.importDirective ?: return false
val importedFqName = importDirective.importedFqName ?: return false
val helper = KtFe10ReferenceResolutionHelper.getInstance()
val importedDescriptors = helper.resolveImportReference(importDirective.containingKtFile, importedFqName)
val importableTargets = unwrappedTargets.mapNotNull {
when {
it is KtConstructor<*> -> it.containingClassOrObject
it is PsiMethod && it.isConstructor -> it.containingClass
else -> it
}
}
val project = element.project
val resolveScope = element.resolveScope
return importedDescriptors.any {
helper.findPsiDeclarations(it, project, resolveScope).any { declaration ->
declaration in importableTargets
}
}
}
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
require(this is KtFe10AnalysisSession)
val bindingContext = KtFe10ReferenceResolutionHelper.getInstance().partialAnalyze(element)
return getTargetDescriptors(bindingContext).mapNotNull { descriptor ->
descriptor.toKtSymbol(analysisContext)
}
}
}
@@ -1,43 +0,0 @@
/*
* Copyright 2010-2022 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.kotlin.analysis.api.descriptors.references.base
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
/**
* Temporary helper that allows FE1.0 KtReferences to use some IDE functionality.
*/
interface KtFe10ReferenceResolutionHelper {
fun isInProjectOrLibSource(element: PsiElement, includeScriptsOutsideSourceRoots: Boolean): Boolean
fun resolveImportReference(file: KtFile, fqName: FqName): Collection<DeclarationDescriptor>
fun partialAnalyze(element: KtElement): BindingContext
fun findDecompiledDeclaration(
project: Project,
referencedDescriptor: DeclarationDescriptor,
builtInsSearchScope: GlobalSearchScope?
): KtDeclaration?
fun findPsiDeclarations(declaration: DeclarationDescriptor, project: Project, resolveScope: GlobalSearchScope): Collection<PsiElement>
fun resolveKDocLink(element: KDocName): Collection<DeclarationDescriptor>
companion object {
fun getInstance() = ApplicationManager.getApplication().getService(KtFe10ReferenceResolutionHelper::class.java)
}
}
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2022 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.kotlin.analysis.api.descriptors.utils
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10ReferenceResolutionHelper
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
object DescriptorToSourceUtilsIde {
// Returns PSI element for descriptor. If there are many relevant elements (e.g. it is fake override
// with multiple declarations), finds any of them. It can find declarations in builtins or decompiled code.
fun getAnyDeclaration(project: Project, descriptor: DeclarationDescriptor): PsiElement? {
return getDeclarationsStream(project, descriptor).firstOrNull()
}
// Returns all PSI elements for descriptor. It can find declarations in builtins or decompiled code.
fun getAllDeclarations(
project: Project,
targetDescriptor: DeclarationDescriptor,
builtInsSearchScope: GlobalSearchScope? = null
): Collection<PsiElement> {
val result = getDeclarationsStream(project, targetDescriptor, builtInsSearchScope).toHashSet()
// filter out elements which are navigate to some other element of the result
// this is needed to avoid duplicated results for references to declaration in same library source file
return result.filter { element -> result.none { element != it && it.navigationElement == element } }
}
private fun getDeclarationsStream(
project: Project, targetDescriptor: DeclarationDescriptor, builtInsSearchScope: GlobalSearchScope? = null
): Sequence<PsiElement> {
val effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(targetDescriptor).asSequence()
return effectiveReferencedDescriptors.flatMap { effectiveReferenced ->
// References in library sources should be resolved to corresponding decompiled declarations,
// therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations
sequenceOfLazyValues(
{ DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) },
{ KtFe10ReferenceResolutionHelper.getInstance().findDecompiledDeclaration(project, effectiveReferenced, builtInsSearchScope) }
)
}.filterNotNull()
}
}