[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.
|
* Returns `null` if visibility cannot be decided by the heuristic.
|
||||||
*/
|
*/
|
||||||
private fun KtFirPsiJavaClassSymbol.isVisibleByPsi(useSiteFile: KtFirFileSymbol): Boolean? {
|
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) {
|
when (visibility) {
|
||||||
Visibilities.Private ->
|
Visibilities.Private ->
|
||||||
// Private classes from Java cannot be accessed from Kotlin.
|
// Private classes from Java cannot be accessed from Kotlin.
|
||||||
@@ -101,7 +94,7 @@ internal class KtFirVisibilityChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
JavaVisibilities.PackageVisibility -> {
|
JavaVisibilities.PackageVisibility -> {
|
||||||
val isSamePackage = classId.packageFqName == useSiteFile.firSymbol.fir.packageFqName
|
val isSamePackage = classIdIfNonLocal.packageFqName == useSiteFile.firSymbol.fir.packageFqName
|
||||||
if (!isSamePackage) return false
|
if (!isSamePackage) return false
|
||||||
|
|
||||||
return when (val outerClass = this.outerClass) {
|
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.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.analysis.api.base.KtContextReceiver
|
import org.jetbrains.kotlin.analysis.api.base.KtContextReceiver
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
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.annotations.KtFirAnnotationListForDeclaration
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||||
@@ -105,6 +104,22 @@ internal class KtFirNamedClassOrObjectSymbol(
|
|||||||
createNamedClassOrObjectSymbolPointer()
|
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 psi: PsiClass,
|
||||||
override val analysisSession: KtFirAnalysisSession,
|
override val analysisSession: KtFirAnalysisSession,
|
||||||
) : KtNamedClassOrObjectSymbol(), KtFirPsiSymbol<PsiClass, FirRegularClassSymbol> {
|
) : 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.
|
* [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 name: Name = withValidityAssertion { javaClass.name }
|
||||||
|
|
||||||
override val classIdIfNonLocal: ClassId? by cached { psi.classIdIfNonLocal }
|
override val classIdIfNonLocal: ClassId = withValidityAssertion {
|
||||||
|
psi.classIdIfNonLocal ?: error("${KtFirPsiJavaClassSymbol::class.simpleName} requires a non-local PSI class.")
|
||||||
private val qualifiedName: String
|
}
|
||||||
get() = withValidityAssertion { psi.qualifiedName!! }
|
|
||||||
|
|
||||||
override val origin: KtSymbolOrigin
|
override val origin: KtSymbolOrigin
|
||||||
get() = withValidityAssertion { KtSymbolOrigin.JAVA }
|
get() = withValidityAssertion { KtSymbolOrigin.JAVA }
|
||||||
|
|
||||||
override val symbolKind: KtSymbolKind
|
override val symbolKind: KtSymbolKind
|
||||||
get() = withValidityAssertion {
|
get() = withValidityAssertion {
|
||||||
val classId = classIdIfNonLocal
|
|
||||||
when {
|
when {
|
||||||
classId == null -> KtSymbolKind.LOCAL
|
classIdIfNonLocal.outerClassId != null -> KtSymbolKind.CLASS_MEMBER
|
||||||
classId.outerClassId != null -> KtSymbolKind.CLASS_MEMBER
|
|
||||||
else -> KtSymbolKind.TOP_LEVEL
|
else -> KtSymbolKind.TOP_LEVEL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +79,7 @@ internal class KtFirPsiJavaClassSymbol(
|
|||||||
get() = withValidityAssertion { javaClass.visibility }
|
get() = withValidityAssertion { javaClass.visibility }
|
||||||
|
|
||||||
override val isInner: Boolean
|
override val isInner: Boolean
|
||||||
get() = withValidityAssertion { classIdIfNonLocal?.outerClassId != null && !javaClass.isStatic }
|
get() = withValidityAssertion { classIdIfNonLocal.outerClassId != null && !javaClass.isStatic }
|
||||||
|
|
||||||
val outerClass: KtFirPsiJavaClassSymbol?
|
val outerClass: KtFirPsiJavaClassSymbol?
|
||||||
get() = withValidityAssertion {
|
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)
|
// Slow Operations (requiring access to the underlying FIR class symbol)
|
||||||
|
|||||||
Reference in New Issue
Block a user