diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt index 073c3497b9d..debc251dae3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/KtReference.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.references import com.intellij.psi.* +import com.intellij.psi.impl.source.resolve.ResolveCache import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor @@ -38,18 +39,14 @@ interface KtReference : PsiPolyVariantReference { val resolvesByNames: Collection } -abstract class AbstractKtReference(element: T) -: PsiPolyVariantReferenceBase(element), KtReference { - +abstract class AbstractKtReference(element: T) : PsiPolyVariantReferenceBase(element), KtReference { val expression: T get() = element override fun multiResolve(incompleteCode: Boolean): Array { - return PsiElementResolveResult.createResults(resolveToPsiElements()) - } - - override fun resolve(): PsiElement? { - return resolveToPsiElements().singleOrNull() + @Suppress("UNCHECKED_CAST") + val kotlinResolver = KOTLIN_RESOLVER as ResolveCache.PolyVariantResolver> + return ResolveCache.getInstance(expression.project).resolveWithCaching(this, kotlinResolver, false, incompleteCode) } override fun isReferenceTo(element: PsiElement?): Boolean { @@ -68,51 +65,64 @@ abstract class AbstractKtReference(element: T) override fun isSoft(): Boolean = false - private fun resolveToPsiElements(): Collection { - val bindingContext = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) - return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext)) - } - override fun resolveToDescriptors(bindingContext: BindingContext): Collection { return getTargetDescriptors(bindingContext) } - private fun resolveToPsiElements(context: BindingContext, targetDescriptors: Collection): Collection { - if (targetDescriptors.isNotEmpty()) { - return targetDescriptors.flatMap { target -> resolveToPsiElements(target) }.toSet() - } - - val labelTargets = getLabelTargets(context) - if (labelTargets != null) { - return labelTargets - } - - return Collections.emptySet() - } - - private fun resolveToPsiElements(targetDescriptor: DeclarationDescriptor): Collection { - if (targetDescriptor is PackageViewDescriptor) { - val psiFacade = JavaPsiFacade.getInstance(expression.project) - val fqName = targetDescriptor.fqName.asString() - return listOfNotNull(psiFacade.findPackage(fqName)) - } - else { - return DescriptorToSourceUtilsIde.getAllDeclarations(expression.project, targetDescriptor, expression.resolveScope) - } - } - protected abstract fun getTargetDescriptors(context: BindingContext): Collection - private fun getLabelTargets(context: BindingContext): Collection? { - val reference = expression as? KtReferenceExpression ?: return null - val labelTarget = context[BindingContext.LABEL_TARGET, reference] - if (labelTarget != null) { - return listOf(labelTarget) - } - return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference] - } - override fun toString() = this::class.java.simpleName + ": " + expression.text + + companion object { + class KotlinReferenceResolver : ResolveCache.PolyVariantResolver> { + class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element) + + private fun resolveToPsiElements(ref: AbstractKtReference): Collection { + val bindingContext = ref.expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) + return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext)) + } + + private fun resolveToPsiElements(ref: AbstractKtReference, 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: AbstractKtReference, targetDescriptor: DeclarationDescriptor): Collection { + if (targetDescriptor is PackageViewDescriptor) { + val psiFacade = JavaPsiFacade.getInstance(ref.expression.project) + val fqName = targetDescriptor.fqName.asString() + return listOfNotNull(psiFacade.findPackage(fqName)) + } + else { + return DescriptorToSourceUtilsIde.getAllDeclarations(ref.expression.project, targetDescriptor, ref.expression.resolveScope) + } + } + + private fun getLabelTargets(ref: AbstractKtReference, context: BindingContext): Collection? { + val reference = ref.expression as? KtReferenceExpression ?: return null + val labelTarget = context[BindingContext.LABEL_TARGET, reference] + if (labelTarget != null) { + return listOf(labelTarget) + } + return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference] + } + + override fun resolve(ref: AbstractKtReference, incompleteCode: Boolean): Array { + val resolveToPsiElements = resolveToPsiElements(ref) + return resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray() + } + } + + val KOTLIN_RESOLVER = KotlinReferenceResolver() + } } abstract class KtSimpleReference(expression: T) : AbstractKtReference(expression) {