IR: use IdSignature to compare classes in FqNameEqualityChecker

This is both simpler and a lot more performant.
This commit is contained in:
Alexander Udalov
2020-08-03 22:48:00 +02:00
parent 36a1a65d98
commit 7503f134c2
@@ -5,82 +5,17 @@
package org.jetbrains.kotlin.ir.symbols
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.util.isLocalClass
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
interface IrClassifierEqualityChecker {
fun areEqual(left: IrClassifierSymbol, right: IrClassifierSymbol): Boolean
fun getHashCode(symbol: IrClassifierSymbol): Int
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
object FqNameEqualityChecker : IrClassifierEqualityChecker {
override fun areEqual(left: IrClassifierSymbol, right: IrClassifierSymbol): Boolean {
if (left === right) return true
if (!left.isBound || !right.isBound) {
return checkViaDescriptors(left.descriptor, right.descriptor)
}
return checkViaDeclarations(left.owner, right.owner)
}
override fun areEqual(left: IrClassifierSymbol, right: IrClassifierSymbol): Boolean =
left === right ||
left.isPublicApi && right.isPublicApi && left.signature == right.signature
override fun getHashCode(symbol: IrClassifierSymbol): Int {
if (symbol.isBound) {
val owner = symbol.owner
if (owner is IrClass && !owner.isLocalClass()) {
return owner.fqName.hashCode()
}
return owner.hashCode()
}
val descriptor = symbol.descriptor
if (descriptor is ClassDescriptor && !DescriptorUtils.isLocal(descriptor)) {
return descriptor.fqNameSafe.hashCode()
}
return descriptor.hashCode()
}
private val IrDeclarationWithName.fqName: FqName?
get() {
val parentFqName = when (val parent = parent) {
is IrPackageFragment -> parent.fqName
is IrDeclarationWithName -> parent.fqName
else -> return null
}
return parentFqName?.child(name)
}
private fun areFqNamesEqual(c1: IrDeclarationWithName, c2: IrDeclarationWithName): Boolean {
if (c1.name != c2.name) return false
val parent1 = c1.parent
val parent2 = c2.parent
return when (parent1) {
is IrPackageFragment -> parent2 is IrPackageFragment && parent1.fqName == parent2.fqName
is IrDeclarationWithName -> parent2 is IrDeclarationWithName && areFqNamesEqual(parent1, parent2)
else -> false
}
}
private fun checkViaDeclarations(c1: IrSymbolOwner, c2: IrSymbolOwner): Boolean {
if (c1 is IrClass && c2 is IrClass) {
if (c1.isLocalClass() || c2.isLocalClass())
return c1 === c2 // Local declarations should be identical
return areFqNamesEqual(c1, c2)
}
return c1 == c2
}
private fun checkViaDescriptors(c1: ClassifierDescriptor, c2: ClassifierDescriptor) = c1.typeConstructor == c2.typeConstructor
override fun getHashCode(symbol: IrClassifierSymbol): Int =
if (symbol.isPublicApi) symbol.signature.hashCode() else symbol.hashCode()
}