From 9db2b6ffba09fc9b9e0d1255e9da9518bc32406d Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Fri, 10 Aug 2018 21:20:47 +0300 Subject: [PATCH] `KtLightPsiJavaCodeReferenceElement` reference getting made lazy (KT-26036, EA-125884) Collecting references from contributors could be expensive and even recursive (EA-125884) --- .../KtLightPsiJavaCodeReferenceElement.kt | 39 +++++++++++++++++-- .../asJava/elements/lightAnnotations.kt | 15 ++++--- .../asJava/elements/lightAnnotations.kt.173 | 15 ++++--- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt index 65abbd76e95..a385caf4c63 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightPsiJavaCodeReferenceElement.kt @@ -5,20 +5,22 @@ package org.jetbrains.kotlin.asJava.elements +import com.intellij.openapi.util.TextRange import com.intellij.psi.* import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.asJava.classes.lazyPub class KtLightPsiJavaCodeReferenceElement( private val ktElement: PsiElement, - private val reference: PsiReference, - private val clsDelegateProvider: () -> PsiJavaCodeReferenceElement? + reference: () -> PsiReference?, + clsDelegateProvider: () -> PsiJavaCodeReferenceElement? ) : PsiElement by ktElement, - PsiReference by reference, + PsiReference by LazyPsiReferenceDelegate(ktElement, reference), PsiJavaCodeReferenceElement { - private val delegate by lazyPub { clsDelegateProvider() } + private val delegate by lazyPub(clsDelegateProvider) override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult = delegate?.advancedResolve(incompleteCode) ?: JavaResolveResult.EMPTY @@ -42,4 +44,33 @@ class KtLightPsiJavaCodeReferenceElement( override fun getQualifier(): PsiElement? = delegate?.qualifier override fun getParameterList(): PsiReferenceParameterList? = delegate?.parameterList +} + +private class LazyPsiReferenceDelegate( + private val psiElement: PsiElement, + referenceProvider: () -> PsiReference? +) : PsiReference { + + private val delegate by lazyPub(referenceProvider) + + override fun getElement(): PsiElement = psiElement + + override fun resolve(): PsiElement? = delegate?.resolve() + + override fun getRangeInElement(): TextRange = delegate?.rangeInElement ?: psiElement.textRange + + override fun getCanonicalText(): String = delegate?.canonicalText ?: "" + + @Throws(IncorrectOperationException::class) + override fun handleElementRename(newElementName: String): PsiElement = delegate?.handleElementRename(newElementName) ?: element + + @Throws(IncorrectOperationException::class) + override fun bindToElement(element: PsiElement): PsiElement = + delegate?.bindToElement(element) ?: throw IncorrectOperationException("can't rename LazyPsiReferenceDelegate") + + override fun isSoft(): Boolean = delegate?.isSoft ?: false + + override fun isReferenceTo(element: PsiElement): Boolean = delegate?.isReferenceTo(element) ?: false + + override fun getVariants(): Array = delegate?.variants ?: emptyArray() } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt index 18dd5825441..7723fbf79e8 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt @@ -127,15 +127,14 @@ class KtLightAnnotationForSourceEntry( } - override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? { - val reference = (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference + override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = KtLightPsiJavaCodeReferenceElement( + kotlinOrigin.navigationElement, + { + (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference ?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull() - ?: return null - return KtLightPsiJavaCodeReferenceElement( - kotlinOrigin.navigationElement, - reference, - { super.getNameReferenceElement() }) - } + }, + { super.getNameReferenceElement() } + ) private val ktLightAnnotationParameterList by lazyPub { KtLightAnnotationParameterList() } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 index b354085e03a..eb480b1d294 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 @@ -129,15 +129,14 @@ class KtLightAnnotationForSourceEntry( } - override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? { - val reference = (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference + override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = KtLightPsiJavaCodeReferenceElement( + kotlinOrigin.navigationElement, + { + (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference ?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull() - ?: return null - return KtLightPsiJavaCodeReferenceElement( - kotlinOrigin.navigationElement, - reference, - { super.getNameReferenceElement() }) - } + }, + { super.getNameReferenceElement() } + ) private val ktLightAnnotationParameterList by lazyPub { KtLightAnnotationParameterList() }