From 44ed90330362779ddeb1d2861127e09e5e37c20b Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 14 Jul 2017 19:58:26 +0300 Subject: [PATCH] Implement equivalence of light members by origin when possible Previous implementation worked through equality that used equality of method stubs (see LightMemberOriginForCompiledMethod). But method stubs for compiled element can be recreated when caches are outdated, including weak reference cleaning (see ClsJavaStubByVirtualFileCache). This could cause misbehave of find usages when java reference has an outdated version of light element in resolution cache. --- .../kotlin/asJava/builder/LightElementOrigin.kt | 6 ++++++ .../kotlin/asJava/elements/KtLightFieldImpl.kt | 7 ------- .../kotlin/asJava/elements/KtLightMemberImpl.kt | 8 ++++++++ .../kotlin/asJava/elements/KtLightMethodImpl.kt | 8 -------- .../LightMemberOriginForCompiledElement.kt | 10 ++++++++++ 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt index 670b17c43e9..f869afa5ccf 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightElementOrigin.kt @@ -50,10 +50,16 @@ interface LightMemberOrigin : LightElementOrigin { override val originalElement: KtDeclaration? override val originKind: JvmDeclarationOriginKind + fun isEquivalentTo(other: LightMemberOrigin?): Boolean fun copy(): LightMemberOrigin } data class LightMemberOriginForDeclaration(override val originalElement: KtDeclaration, override val originKind: JvmDeclarationOriginKind) : LightMemberOrigin { + override fun isEquivalentTo(other: LightMemberOrigin?): Boolean { + if (other !is LightMemberOriginForDeclaration) return false + return originalElement.isEquivalentTo(other.originalElement) + } + override fun copy(): LightMemberOrigin { return LightMemberOriginForDeclaration(originalElement.copy() as KtDeclaration, originKind) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt index 3d5cce42896..8ffbbe06776 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt @@ -70,13 +70,6 @@ sealed class KtLightFieldImpl( return (clsDelegate as PsiVariableEx).computeConstantValue(visitedVars) } - override fun isEquivalentTo(another: PsiElement?): Boolean { - if (another is KtLightField && this == another) { - return true - } - return super.isEquivalentTo(another) - } - override fun copy() = Factory.create(lightMemberOrigin?.copy(), clsDelegate, containingClass) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt index d913a071b54..21e85ca0dfe 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMemberImpl.kt @@ -64,6 +64,14 @@ abstract class KtLightMemberImpl( override fun getDocComment() = (clsDelegate as PsiDocCommentOwner).docComment override fun isDeprecated() = (clsDelegate as PsiDocCommentOwner).isDeprecated + + override fun isEquivalentTo(another: PsiElement?): Boolean { + val isEquivalentByOrigin = + another is KtLightMember<*> && + lightMemberOrigin?.isEquivalentTo(another.lightMemberOrigin) == true + + return isEquivalentByOrigin || this == another + } } internal fun getMemberOrigin(member: PsiMember): LightMemberOriginForDeclaration? { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt index 692934a7677..39f8598cc5d 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt @@ -139,14 +139,6 @@ class KtLightMethodImpl private constructor( return typeParameters.all { processor.execute(it, state) } } - override fun isEquivalentTo(another: PsiElement?): Boolean { - if (another is KtLightMethod && this == another) { - return true - } - - return super.isEquivalentTo(another) - } - private val _memberIndex: MemberIndex? get() = (dummyDelegate ?: clsDelegate).memberIndex diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LightMemberOriginForCompiledElement.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LightMemberOriginForCompiledElement.kt index 86d6268b1f8..4974a1ba59a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LightMemberOriginForCompiledElement.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LightMemberOriginForCompiledElement.kt @@ -52,6 +52,11 @@ data class LightMemberOriginForCompiledField(val psiField: PsiField, val file: K return LightMemberOriginForCompiledField(psiField.copy() as PsiField, file) } + override fun isEquivalentTo(other: LightMemberOrigin?): Boolean { + if (other !is LightMemberOriginForCompiledField) return false + return psiField.isEquivalentTo(other.psiField) + } + override val originalElement: KtDeclaration? by lazyPub { val desc = MapPsiToAsmDesc.typeDesc(psiField.type) val signature = MemberSignature.fromFieldNameAndDesc(psiField.name!!, desc) @@ -60,6 +65,11 @@ data class LightMemberOriginForCompiledField(val psiField: PsiField, val file: K } data class LightMemberOriginForCompiledMethod(val psiMethod: PsiMethod, val file: KtClsFile) : LightMemberOriginForCompiledElement { + override fun isEquivalentTo(other: LightMemberOrigin?): Boolean { + if (other !is LightMemberOriginForCompiledMethod) return false + return psiMethod.isEquivalentTo(other.psiMethod) + } + override fun copy(): LightMemberOrigin { return LightMemberOriginForCompiledMethod(psiMethod.copy() as PsiMethod, file) }