FIR IDE: make equality of KtSymbol/KtType stable
This commit is contained in:
committed by
Ilya Kirillov
parent
6b57621863
commit
7306f1c3f1
+19
-1
@@ -6,10 +6,28 @@
|
||||
package org.jetbrains.kotlin.idea.frontend.api.symbols.markers
|
||||
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
|
||||
public abstract class KtTypeAndAnnotations : ValidityTokenOwner {
|
||||
public abstract val type: KtType
|
||||
public abstract val annotations: List<KtAnnotationCall>
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KtTypeAndAnnotations
|
||||
|
||||
if (token != other.token) return false
|
||||
if (type != other.type) return false
|
||||
if (annotations != other.annotations) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = token.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
result = 31 * result + annotations.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
+3
@@ -53,4 +53,7 @@ internal class KtFirAnonymousFunctionSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
error("Could not create a pointer for anonymous function from library")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -46,4 +46,7 @@ internal class KtFirAnonymousObjectSymbol(
|
||||
override fun createPointer(): KtSymbolPointer<KtAnonymousObjectSymbol> =
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)
|
||||
?: throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException("Cannot create pointer for KtFirAnonymousObjectSymbol")
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+14
@@ -39,4 +39,18 @@ internal class KtFirBackingFieldSymbol(
|
||||
override fun createPointer(): KtSymbolPointer<KtBackingFieldSymbol> {
|
||||
return KtFirBackingFieldSymbolPointer(owningProperty.createPointer())
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KtFirBackingFieldSymbol
|
||||
|
||||
if (this.token != other.token) return false
|
||||
return this.propertyFirRef == other.propertyFirRef
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return propertyFirRef.hashCode() * 31 + token.hashCode()
|
||||
}
|
||||
}
|
||||
+3
@@ -87,4 +87,7 @@ internal class KtFirConstructorSymbol(
|
||||
?: error("ClassId should present for member declaration")
|
||||
return KtFirConstructorSymbolPointer(ownerClassId, isPrimary, firRef.withFir { it.createSignature() })
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -55,4 +55,7 @@ internal class KtFirEnumEntrySymbol(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -38,4 +38,7 @@ internal class KtFirFileSymbol(
|
||||
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
|
||||
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
|
||||
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -120,4 +120,7 @@ internal class KtFirFunctionSymbol(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -50,4 +50,7 @@ internal class KtFirJavaFieldSymbol(
|
||||
override fun createPointer(): KtSymbolPointer<KtJavaFieldSymbol> {
|
||||
TODO("Creating pointers for java fields is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -129,4 +129,7 @@ internal class KtFirKotlinPropertySymbol(
|
||||
KtSymbolKind.LOCAL -> throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -49,4 +49,7 @@ internal class KtFirLocalVariableSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(name.asString())
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -114,4 +114,7 @@ internal class KtFirNamedClassOrObjectSymbol(
|
||||
}
|
||||
return KtFirClassOrObjectInLibrarySymbolPointer(classIdIfNonLocal!!)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+18
@@ -38,6 +38,24 @@ class KtFirPackageSymbol(
|
||||
check(session is KtFirAnalysisSession)
|
||||
session.firSymbolBuilder.createPackageSymbolIfOneExists(fqName)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KtFirPackageSymbol
|
||||
|
||||
if (fqName != other.fqName) return false
|
||||
if (token != other.token) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = fqName.hashCode()
|
||||
result = 31 * result + token.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class KtPackage(
|
||||
|
||||
+3
@@ -67,4 +67,7 @@ internal class KtFirPropertyGetterSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
TODO("Creating pointers for getters from library is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -74,4 +74,7 @@ internal class KtFirPropertySetterSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
TODO("Creating pointers for setters from library is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+7
@@ -24,6 +24,13 @@ internal interface KtFirSymbol<out F : FirDeclaration> : KtSymbol, ValidityToken
|
||||
override val origin: KtSymbolOrigin get() = firRef.withFir { it.ktSymbolOrigin() }
|
||||
}
|
||||
|
||||
internal fun KtFirSymbol<*>.symbolEquals(other: Any?): Boolean {
|
||||
if (other !is KtFirSymbol<*>) return false
|
||||
if (this.token != other.token) return false
|
||||
return this.firRef == other.firRef
|
||||
}
|
||||
|
||||
internal fun KtFirSymbol<*>.symbolHashCode(): Int = firRef.hashCode() * 31 + token.hashCode()
|
||||
|
||||
private tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (origin) {
|
||||
FirDeclarationOrigin.Source -> {
|
||||
|
||||
+3
@@ -93,4 +93,7 @@ internal class KtFirSyntheticJavaPropertySymbol(
|
||||
override fun createPointer(): KtSymbolPointer<KtSyntheticJavaPropertySymbol> {
|
||||
TODO("pointers to KtSyntheticJavaPropertySymbol is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -42,4 +42,7 @@ internal class KtFirTypeAliasSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
TODO("Creating symbols for library typealiases is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -44,4 +44,7 @@ internal class KtFirTypeParameterSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
TODO("Creating symbols for library type parameters is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+3
@@ -52,4 +52,7 @@ internal class KtFirValueParameterSymbol(
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }
|
||||
TODO("Creating pointers for functions parameters from library is not supported yet")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+10
@@ -43,4 +43,14 @@ internal class KtFirAnnotationCall(
|
||||
KtNamedConstantValue(name, expression.convertConstantExpression())
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is KtFirAnnotationCall) return false
|
||||
if (this.token != other.token) return false
|
||||
return annotationCallRef == other.annotationCallRef
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return token.hashCode() * 31 + annotationCallRef.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
+28
-1
@@ -9,7 +9,9 @@ import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.receiverType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtTypeArgument
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtTypeArgumentWithVariance
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||
@@ -17,6 +19,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -24,6 +27,14 @@ internal interface KtFirType : ValidityTokenOwner {
|
||||
val coneType: ConeKotlinType
|
||||
}
|
||||
|
||||
private fun KtFirType.typeEquals(other: Any?): Boolean {
|
||||
if (other !is KtFirType) return false
|
||||
if (this.token != other.token) return false
|
||||
return this.coneType == other.coneType
|
||||
}
|
||||
|
||||
private fun KtFirType.typeHashcode(): Int = token.hashCode() * 31 + coneType.hashCode()
|
||||
|
||||
internal class KtFirUsualClassType(
|
||||
_coneType: ConeClassLikeTypeImpl,
|
||||
override val token: ValidityToken,
|
||||
@@ -45,6 +56,8 @@ internal class KtFirUsualClassType(
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { KtTypeNullability.create(coneType.canBeNull) }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirFunctionalType(
|
||||
@@ -96,6 +109,8 @@ internal class KtFirFunctionalType(
|
||||
get() = withValidityAssertion { (typeArguments.last() as KtTypeArgumentWithVariance).type }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirClassErrorType(
|
||||
@@ -106,6 +121,8 @@ internal class KtFirClassErrorType(
|
||||
|
||||
override val error: String get() = withValidityAssertion { coneType.diagnostic.reason }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirCapturedType(
|
||||
@@ -114,6 +131,8 @@ internal class KtFirCapturedType(
|
||||
) : KtCapturedType(), KtFirType {
|
||||
override val coneType by weakRef(_coneType)
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirDefinitelyNotNullType(
|
||||
@@ -127,6 +146,8 @@ internal class KtFirDefinitelyNotNullType(
|
||||
override val original: KtType by cached { builder.typeBuilder.buildKtType(this.coneType.original) }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirTypeParameterType(
|
||||
@@ -145,6 +166,8 @@ internal class KtFirTypeParameterType(
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { KtTypeNullability.create(coneType.canBeNull) }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirFlexibleType(
|
||||
@@ -158,6 +181,8 @@ internal class KtFirFlexibleType(
|
||||
override val lowerBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.lowerBound) }
|
||||
override val upperBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.upperBound) }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
internal class KtFirIntersectionType(
|
||||
@@ -173,4 +198,6 @@ internal class KtFirIntersectionType(
|
||||
}
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+13
@@ -66,6 +66,19 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
ValidityAwareCachedValue(token) {
|
||||
withFirByType(type) { fir -> createValue(fir) }
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is FirRefWithValidityCheck<*>) return false
|
||||
return getRefFir() == other.getRefFir() && this.token == other.token
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return getRefFir().hashCode() * 31 + token.hashCode()
|
||||
}
|
||||
|
||||
private fun getRefFir(): FirDeclaration {
|
||||
return firWeakRef.get() ?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
Reference in New Issue
Block a user