[Analysis API] Add KtFe10ReferenceResolutionHelper and ...
Make implementation of KtFe10XXXReference follow the old descriptor-based implementation as closely as possible.
This commit is contained in:
committed by
Ilya Kirillov
parent
b5139c958b
commit
0803ab0d0b
+10
-11
@@ -6,22 +6,21 @@
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.references.KtArrayAccessReference
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
|
||||
import org.jetbrains.kotlin.psi.KtImportAlias
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class KtFe10ArrayAccessReference(expression: KtArrayAccessExpression) : KtArrayAccessReference(expression), KtFe10Reference {
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
|
||||
val bindingContext = analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
val descriptor = expression.getResolvedCall(bindingContext)?.resultingDescriptor
|
||||
return listOfNotNull(descriptor?.toKtCallableSymbol(analysisContext))
|
||||
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)
|
||||
}
|
||||
}
|
||||
+8
-10
@@ -5,24 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
|
||||
return listOfNotNull(resolvedCall?.resultingDescriptor)
|
||||
}
|
||||
|
||||
val bindingContext = analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
val descriptor = bindingContext[BindingContext.COLLECTION_LITERAL_CALL, expression]?.resultingDescriptor
|
||||
return listOfNotNull(descriptor?.toKtCallableSymbol(analysisContext))
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-11
@@ -5,24 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.idea.references.KtConstructorDelegationReference
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
|
||||
|
||||
val bindingContext = analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
val descriptor = expression.getResolvedCall(bindingContext)?.resultingDescriptor
|
||||
return listOfNotNull(descriptor?.toKtCallableSymbol(analysisContext))
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
}
|
||||
+28
-10
@@ -5,24 +5,42 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFe10AnalysisSession)
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
return listOfNotNull(
|
||||
context[BindingContext.VARIABLE, element],
|
||||
context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor
|
||||
)
|
||||
}
|
||||
|
||||
val bindingContext = analysisContext.analyze(element, AnalysisMode.PARTIAL)
|
||||
val descriptor = bindingContext[BindingContext.COMPONENT_RESOLVED_CALL, element]?.resultingDescriptor
|
||||
return listOfNotNull(descriptor?.toKtCallableSymbol(analysisContext))
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-12
@@ -5,26 +5,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFe10AnalysisSession)
|
||||
|
||||
val loopRange = element.loopRange ?: return emptyList()
|
||||
val bindingContext = analysisContext.analyze(loopRange)
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val loopRange = expression.loopRange ?: return emptyList()
|
||||
return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor }
|
||||
}
|
||||
|
||||
return listOf(
|
||||
companion object {
|
||||
private val LOOP_RANGE_KEYS = arrayOf(
|
||||
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
|
||||
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL,
|
||||
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL
|
||||
).mapNotNull { slice -> bindingContext[slice, loopRange]?.resultingDescriptor?.toKtCallableSymbol(analysisContext) }
|
||||
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
|
||||
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
|
||||
)
|
||||
}
|
||||
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
}
|
||||
+13
-15
@@ -5,35 +5,33 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
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.KtExpression
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
|
||||
val bindingContext = analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
val call = expression.getCall(bindingContext)
|
||||
val resolvedCall = call.getResolvedCall(bindingContext)
|
||||
val descriptors = when {
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val call = element.getCall(context)
|
||||
val resolvedCall = call.getResolvedCall(context)
|
||||
return when {
|
||||
resolvedCall is VariableAsFunctionResolvedCall ->
|
||||
setOf((resolvedCall as VariableAsFunctionResolvedCall).functionCall.resultingDescriptor)
|
||||
setOf<DeclarationDescriptor>((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor)
|
||||
call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE ->
|
||||
setOf(resolvedCall.resultingDescriptor)
|
||||
setOf<DeclarationDescriptor>(resolvedCall.candidateDescriptor)
|
||||
else ->
|
||||
emptyList()
|
||||
}
|
||||
return descriptors.mapNotNull { it.toKtCallableSymbol(analysisContext) }
|
||||
}
|
||||
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-23
@@ -5,39 +5,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
|
||||
val property = expression.parent as? KtProperty
|
||||
if (property == null || property.delegate !== element) {
|
||||
return emptyList()
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
val bindingContext = analysisContext.analyze(property)
|
||||
val propertyDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, property]
|
||||
|
||||
if (propertyDescriptor is PropertyDescriptor) {
|
||||
return listOfNotNull(propertyDescriptor.getter, propertyDescriptor.setter)
|
||||
.mapNotNull { accessor ->
|
||||
val descriptor = bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor]?.resultingDescriptor
|
||||
descriptor?.toKtCallableSymbol(analysisContext)
|
||||
}
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
|
||||
return super<KtFe10Reference>.isReferenceToImportAlias(alias)
|
||||
}
|
||||
}
|
||||
+62
-15
@@ -6,33 +6,80 @@
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.references.base.KtFe10Reference
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
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.calls.util.getResolvedCall
|
||||
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 KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
require(this is KtFe10AnalysisSession)
|
||||
|
||||
val bindingContext = analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
|
||||
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, expression]
|
||||
?: expression.getResolvedCall(bindingContext)?.resultingDescriptor
|
||||
|
||||
return listOfNotNull(descriptor?.toKtSymbol(analysisContext))
|
||||
override fun canBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
||||
return element.containingFile == candidateTarget.containingFile ||
|
||||
KtFe10ReferenceResolutionHelper.getInstance().isInProjectOrLibSource(element, includeScriptsOutsideSourceRoots = true)
|
||||
}
|
||||
|
||||
override fun isReferenceToViaExtension(element: PsiElement): Boolean = false
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+57
-23
@@ -5,38 +5,72 @@
|
||||
|
||||
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.KtAllowAnalysisOnEdt
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt
|
||||
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.load.kotlin.toSourceElement
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import java.util.*
|
||||
|
||||
object KtFe10PolyVariantResolver : ResolveCache.PolyVariantResolver<KtReference> {
|
||||
@OptIn(KtAllowAnalysisOnEdt::class)
|
||||
override fun resolve(reference: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||
require(reference is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${reference::class}" }
|
||||
return allowAnalysisOnEdt {
|
||||
val expression = reference.expression
|
||||
analyze(reference.expression) {
|
||||
val analysisSession = this as KtFe10AnalysisSession
|
||||
val bindingContext = analysisSession.analysisContext.analyze(expression, AnalysisMode.PARTIAL)
|
||||
val descriptor = when (expression) {
|
||||
is KtReferenceExpression -> bindingContext[BindingContext.REFERENCE_TARGET, expression]
|
||||
else -> expression.getResolvedCall(bindingContext)?.resultingDescriptor
|
||||
}
|
||||
val source = descriptor?.toSourceElement?.getPsi()
|
||||
if (source != null) arrayOf(PsiElementResolveResult(source)) else emptyArray()
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
+46
@@ -5,11 +5,57 @@
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.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>
|
||||
|
||||
companion object {
|
||||
fun getInstance() = ApplicationManager.getApplication().getService(KtFe10ReferenceResolutionHelper::class.java)
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
|
||||
import org.jetbrains.kotlin.resolve.references.ReferenceAccess
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.constant
|
||||
|
||||
interface ReadWriteAccessChecker {
|
||||
fun readWriteAccessWithFullExpressionByResolve(assignment: KtBinaryExpression): Pair<ReferenceAccess, KtExpression>?
|
||||
|
||||
fun readWriteAccessWithFullExpression(
|
||||
targetExpression: KtExpression,
|
||||
useResolveForReadWrite: Boolean
|
||||
): Pair<ReferenceAccess, KtExpression> {
|
||||
var expression = targetExpression.getQualifiedExpressionForSelectorOrThis()
|
||||
loop@ while (true) {
|
||||
when (val parent = expression.parent) {
|
||||
is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
|
||||
else -> break@loop
|
||||
}
|
||||
}
|
||||
|
||||
val assignment = expression.getAssignmentByLHS()
|
||||
if (assignment != null) {
|
||||
return when (assignment.operationToken) {
|
||||
KtTokens.EQ -> ReferenceAccess.WRITE to assignment
|
||||
|
||||
else -> {
|
||||
(if (useResolveForReadWrite) readWriteAccessWithFullExpressionByResolve(assignment) else null)
|
||||
?: (ReferenceAccess.READ_WRITE to assignment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val unaryExpression = expression.parent as? KtUnaryExpression
|
||||
return if (unaryExpression != null && unaryExpression.operationToken in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) })
|
||||
ReferenceAccess.READ_WRITE to unaryExpression
|
||||
else
|
||||
ReferenceAccess.READ to expression
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(): ReadWriteAccessChecker = ApplicationManager.getApplication().getService(ReadWriteAccessChecker::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtExpression.readWriteAccessWithFullExpression(useResolveForReadWrite: Boolean): Pair<ReferenceAccess, KtExpression> =
|
||||
ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite)
|
||||
|
||||
fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean): ReferenceAccess =
|
||||
ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite).first
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.plugin.references
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
interface SimpleNameReferenceExtension {
|
||||
companion object {
|
||||
val EP_NAME: ExtensionPointName<SimpleNameReferenceExtension> =
|
||||
ExtensionPointName.create("org.jetbrains.kotlin.simpleNameReferenceExtension")
|
||||
}
|
||||
|
||||
fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean
|
||||
|
||||
fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement?
|
||||
}
|
||||
Reference in New Issue
Block a user