[AA] KT-56617 Sync hashCode/equals of Java and regular class symbols
- Some completion tests failed because the `hashCode` of `KtFirNamedClassOrObjectSymbol` and `KtFirPsiJavaClassSymbol` was different for symbols which should be equal. Both symbols now use the `ClassId` hash code. - `KtFirNamedClassOrObjectSymbol.equals` is now properly symmetric with `KtFirPsiJavaClassSymbol`. - `KtFirPsiJavaClassSymbol` now has a definite class ID, which simplifies its implementation a little. `KtFirPsiJavaClassSymbol` doesn't support local Java classes by design.
This commit is contained in:
committed by
Space Team
parent
f9fb718b37
commit
c729435765
+1
-8
@@ -82,13 +82,6 @@ internal class KtFirVisibilityChecker(
|
||||
* Returns `null` if visibility cannot be decided by the heuristic.
|
||||
*/
|
||||
private fun KtFirPsiJavaClassSymbol.isVisibleByPsi(useSiteFile: KtFirFileSymbol): Boolean? {
|
||||
val classId = classIdIfNonLocal
|
||||
if (classId == null) {
|
||||
// Local classes are only visible in their containing method. Since we're checking the visibility for a Kotlin file, a local
|
||||
// class from Java can never be accessible.
|
||||
return false
|
||||
}
|
||||
|
||||
when (visibility) {
|
||||
Visibilities.Private ->
|
||||
// Private classes from Java cannot be accessed from Kotlin.
|
||||
@@ -101,7 +94,7 @@ internal class KtFirVisibilityChecker(
|
||||
}
|
||||
|
||||
JavaVisibilities.PackageVisibility -> {
|
||||
val isSamePackage = classId.packageFqName == useSiteFile.firSymbol.fir.packageFqName
|
||||
val isSamePackage = classIdIfNonLocal.packageFqName == useSiteFile.firSymbol.fir.packageFqName
|
||||
if (!isSamePackage) return false
|
||||
|
||||
return when (val outerClass = this.outerClass) {
|
||||
|
||||
+18
-3
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.base.KtContextReceiver
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForDeclaration
|
||||
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
@@ -105,6 +104,22 @@ internal class KtFirNamedClassOrObjectSymbol(
|
||||
createNamedClassOrObjectSymbolPointer()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
/**
|
||||
* [KtFirNamedClassOrObjectSymbol] must be able to equal [KtFirPsiJavaClassSymbol].
|
||||
*/
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other === this) return true
|
||||
|
||||
return when (other) {
|
||||
is KtFirNamedClassOrObjectSymbol -> symbolEquals(other)
|
||||
is KtFirPsiJavaClassSymbol -> other == this
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-local [KtFirNamedClassOrObjectSymbol] must have the same kind of hash code as [KtFirPsiJavaClassSymbol] so that they are
|
||||
* interchangeable in collections.
|
||||
*/
|
||||
override fun hashCode(): Int = classIdIfNonLocal?.hashCode() ?: symbolHashCode()
|
||||
}
|
||||
|
||||
+9
-16
@@ -46,12 +46,6 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
override val psi: PsiClass,
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
) : KtNamedClassOrObjectSymbol(), KtFirPsiSymbol<PsiClass, FirRegularClassSymbol> {
|
||||
init {
|
||||
require(psi.qualifiedName != null) {
|
||||
"${KtFirPsiJavaClassSymbol::class.simpleName} requires a PSI class with a qualified name."
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [javaClass] is used to defer some properties to the compiler's view of a Java class.
|
||||
*/
|
||||
@@ -59,20 +53,17 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
|
||||
override val name: Name = withValidityAssertion { javaClass.name }
|
||||
|
||||
override val classIdIfNonLocal: ClassId? by cached { psi.classIdIfNonLocal }
|
||||
|
||||
private val qualifiedName: String
|
||||
get() = withValidityAssertion { psi.qualifiedName!! }
|
||||
override val classIdIfNonLocal: ClassId = withValidityAssertion {
|
||||
psi.classIdIfNonLocal ?: error("${KtFirPsiJavaClassSymbol::class.simpleName} requires a non-local PSI class.")
|
||||
}
|
||||
|
||||
override val origin: KtSymbolOrigin
|
||||
get() = withValidityAssertion { KtSymbolOrigin.JAVA }
|
||||
|
||||
override val symbolKind: KtSymbolKind
|
||||
get() = withValidityAssertion {
|
||||
val classId = classIdIfNonLocal
|
||||
when {
|
||||
classId == null -> KtSymbolKind.LOCAL
|
||||
classId.outerClassId != null -> KtSymbolKind.CLASS_MEMBER
|
||||
classIdIfNonLocal.outerClassId != null -> KtSymbolKind.CLASS_MEMBER
|
||||
else -> KtSymbolKind.TOP_LEVEL
|
||||
}
|
||||
}
|
||||
@@ -88,7 +79,7 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
get() = withValidityAssertion { javaClass.visibility }
|
||||
|
||||
override val isInner: Boolean
|
||||
get() = withValidityAssertion { classIdIfNonLocal?.outerClassId != null && !javaClass.isStatic }
|
||||
get() = withValidityAssertion { classIdIfNonLocal.outerClassId != null && !javaClass.isStatic }
|
||||
|
||||
val outerClass: KtFirPsiJavaClassSymbol?
|
||||
get() = withValidityAssertion {
|
||||
@@ -128,9 +119,11 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
}
|
||||
|
||||
/**
|
||||
* Since [PsiEquivalenceUtil] doesn't have a hash code function, we use the class's fully qualified name as a conservative hash code.
|
||||
* Since [PsiEquivalenceUtil] doesn't have a hash code function, we use the class ID as a conservative hash code.
|
||||
*
|
||||
* Also see [KtFirNamedClassOrObjectSymbol.hashCode], which must generate the same hash code for non-local classes.
|
||||
*/
|
||||
override fun hashCode(): Int = qualifiedName.hashCode()
|
||||
override fun hashCode(): Int = classIdIfNonLocal.hashCode()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Slow Operations (requiring access to the underlying FIR class symbol)
|
||||
|
||||
Reference in New Issue
Block a user