diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ArrayAccessReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ArrayAccessReference.kt index 72c231dbf63..29b0334d639 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ArrayAccessReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ArrayAccessReference.kt @@ -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 { - require(this is KtFe10AnalysisSession) + override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean { + return super.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 { + val getFunctionDescriptor = context[BindingContext.INDEXED_LVALUE_GET, expression]?.candidateDescriptor + val setFunctionDescriptor = context[BindingContext.INDEXED_LVALUE_SET, expression]?.candidateDescriptor + return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor) } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10CollectionLiteralReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10CollectionLiteralReference.kt index eafa31c7d9b..cf14248fd74 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10CollectionLiteralReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10CollectionLiteralReference.kt @@ -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 { - require(this is KtFe10AnalysisSession) + override fun getTargetDescriptors(context: BindingContext): Collection { + 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.isReferenceToImportAlias(alias) } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ConstructorDelegationReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ConstructorDelegationReference.kt index 22e081adbbf..833e0acc03f 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ConstructorDelegationReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ConstructorDelegationReference.kt @@ -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 { - 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.isReferenceToImportAlias(alias) } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10DestructuringDeclarationEntry.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10DestructuringDeclarationEntry.kt index ab2e65743e4..04246d7369f 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10DestructuringDeclarationEntry.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10DestructuringDeclarationEntry.kt @@ -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 { - check(this is KtFe10AnalysisSession) + override fun getTargetDescriptors(context: BindingContext): Collection { + 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.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 + } } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ForLoopInReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ForLoopInReference.kt index 87fe7b81fb0..8e3ff1993a8 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ForLoopInReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10ForLoopInReference.kt @@ -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 { - check(this is KtFe10AnalysisSession) - val loopRange = element.loopRange ?: return emptyList() - val bindingContext = analysisContext.analyze(loopRange) + override fun getTargetDescriptors(context: BindingContext): Collection { + 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.isReferenceToImportAlias(alias) } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10InvokeFunctionReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10InvokeFunctionReference.kt index 72eb9e465fd..d93bf136cb6 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10InvokeFunctionReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10InvokeFunctionReference.kt @@ -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 { - 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 { + val call = element.getCall(context) + val resolvedCall = call.getResolvedCall(context) + return when { resolvedCall is VariableAsFunctionResolvedCall -> - setOf((resolvedCall as VariableAsFunctionResolvedCall).functionCall.resultingDescriptor) + setOf((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor) call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE -> - setOf(resolvedCall.resultingDescriptor) + setOf(resolvedCall.candidateDescriptor) else -> emptyList() } - return descriptors.mapNotNull { it.toKtCallableSymbol(analysisContext) } + } + + override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean { + return super.isReferenceToImportAlias(alias) } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10PropertyDelegationMethodsReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10PropertyDelegationMethodsReference.kt index dee70cb0950..1d8a48bbd26 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10PropertyDelegationMethodsReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10PropertyDelegationMethodsReference.kt @@ -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 { - require(this is KtFe10AnalysisSession) - val property = expression.parent as? KtProperty - if (property == null || property.delegate !== element) { - return emptyList() - } + override fun getTargetDescriptors(context: BindingContext): Collection { + val property = expression.getStrictParentOfType() ?: 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.isReferenceToImportAlias(alias) } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10SimpleNameReference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10SimpleNameReference.kt index e581b1ef9d7..35d37c3a5aa 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10SimpleNameReference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/KtFe10SimpleNameReference.kt @@ -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 { - 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.isReferenceToImportAlias(alias) + } + + override fun getTargetDescriptors(context: BindingContext): Collection { + return SmartList().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 } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10PolyVariantResolver.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10PolyVariantResolver.kt index 8a4282e3e3b..1e91ea9458e 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10PolyVariantResolver.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10PolyVariantResolver.kt @@ -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 { - @OptIn(KtAllowAnalysisOnEdt::class) - override fun resolve(reference: KtReference, incompleteCode: Boolean): Array { - 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 { + 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 + ): Collection { + 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 = 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? { + 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 { + require(ref is KtFe10Reference) { "reference should be KtFe10Reference, but was ${ref::class}" } + val resolveToPsiElements = resolveToPsiElements(ref) + return resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray() } } \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10Reference.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10Reference.kt index 28e0315aa31..ba65b05933c 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10Reference.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10Reference.kt @@ -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 get() = KtFe10PolyVariantResolver + + fun resolveToDescriptors(bindingContext: BindingContext): Collection = getTargetDescriptors(bindingContext) + + fun getTargetDescriptors(context: BindingContext): Collection + + 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 { + require(this is KtFe10AnalysisSession) + val bindingContext = KtFe10ReferenceResolutionHelper.getInstance().partialAnalyze(element) + return getTargetDescriptors(bindingContext).mapNotNull { descriptor -> + descriptor.toKtSymbol(analysisContext) + } + } } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10ReferenceResolutionHelper.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10ReferenceResolutionHelper.kt new file mode 100644 index 00000000000..14358208e07 --- /dev/null +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/references/base/KtFe10ReferenceResolutionHelper.kt @@ -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 + + fun partialAnalyze(element: KtElement): BindingContext + + fun findDecompiledDeclaration( + project: Project, + referencedDescriptor: DeclarationDescriptor, + builtInsSearchScope: GlobalSearchScope? + ): KtDeclaration? + + fun findPsiDeclarations(declaration: DeclarationDescriptor, project: Project, resolveScope: GlobalSearchScope): Collection + + companion object { + fun getInstance() = ApplicationManager.getApplication().getService(KtFe10ReferenceResolutionHelper::class.java) + } +} \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/DescriptorsToSourceUtilsIde.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/DescriptorsToSourceUtilsIde.kt new file mode 100644 index 00000000000..ce39f21bd06 --- /dev/null +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/DescriptorsToSourceUtilsIde.kt @@ -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 { + 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 { + 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() + } +} diff --git a/analysis/kt-references/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt b/analysis/kt-references/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt new file mode 100644 index 00000000000..576f5e561fd --- /dev/null +++ b/analysis/kt-references/src/org/jetbrains/kotlin/idea/references/ReadWriteAccessChecker.kt @@ -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? + + fun readWriteAccessWithFullExpression( + targetExpression: KtExpression, + useResolveForReadWrite: Boolean + ): Pair { + 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 = + ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite) + +fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean): ReferenceAccess = + ReadWriteAccessChecker.getInstance().readWriteAccessWithFullExpression(this, useResolveForReadWrite).first + diff --git a/analysis/kt-references/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt b/analysis/kt-references/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt new file mode 100644 index 00000000000..a4db26bae55 --- /dev/null +++ b/analysis/kt-references/src/org/jetbrains/kotlin/plugin/references/SimpleNameReferenceExtension.kt @@ -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 = + ExtensionPointName.create("org.jetbrains.kotlin.simpleNameReferenceExtension") + } + + fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean + + fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement? +}