Fir2Ir: deal with toplevel privates

This commit is contained in:
Georgy Bronnikov
2021-12-22 19:01:06 +03:00
committed by Alexander Udalov
parent 9ea14a6eab
commit 8771ce94ef
4 changed files with 79 additions and 11 deletions
@@ -322,6 +322,10 @@ open class FirJvmMangleComputer(
override fun visitConstructor(constructor: FirConstructor, data: Boolean) =
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Boolean) {
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol!!.fir)
}
override fun computeMangle(declaration: FirDeclaration): String {
declaration.accept(this, true)
return builder.toString()
@@ -113,8 +113,7 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
}
}
// The next line should have singleOrNull, but in some cases we get multiple references to the same FIR declaration.
val firDeclaration = firCandidates.firstOrNull { fir2IrComponents.signatureComposer.composeSignature(it) == signature }
val firDeclaration = findDeclarationByHash(firCandidates, signature.id)
?: return null
return when (kind) {
@@ -138,4 +137,15 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
else -> error("Don't know how to deal with this symbol kind: $kind")
}
}
private fun findDeclarationByHash(candidates: Collection<FirDeclaration>, hash: Long?): FirDeclaration? =
candidates.firstOrNull { candidate ->
if (hash == null) {
// We don't compute id for type aliases and classes.
candidate is FirClass || candidate is FirTypeAlias
} else {
// The next line should have singleOrNull, but in some cases we get multiple references to the same FIR declaration.
with(fir2IrComponents.signatureComposer.mangler) { candidate.signatureMangle(compatibleMode = false) == hash }
}
}
}
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.visibility
@@ -16,7 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.ir.util.IdSignature
@NoMutableState
// @NoMutableState -- we'll restore this annotation once we get rid of withFileSignature().
class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignatureComposer {
var fileSignature: IdSignature.FileSignature? = null
@@ -80,7 +82,7 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat
} catch (t: Throwable) {
throw IllegalStateException("Error while composing signature for ${declaration.render()}", t)
}
return when (declaration) {
val publicSignature = when (declaration) {
is FirRegularClass -> {
// TODO: private classes are probably not acceptable here too
val classId = declaration.classId
@@ -96,7 +98,7 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat
)
}
is FirCallableDeclaration -> {
if (declaration.visibility == Visibilities.Private) return null
if (declaration.visibility == Visibilities.Private && !isTopLevelPrivate(declaration, containingClass)) return null
val containingClassId = containingClass?.classId
val classId = containingClassId ?: declaration.containingClass()?.classId
@@ -111,6 +113,11 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat
}
else -> error("Unsupported FIR declaration in signature composer: ${declaration.render()}")
}
return if (isTopLevelPrivate(declaration, containingClass)) {
val fileSig = fileSignature ?: return null
IdSignature.CompositeSignature(fileSig, publicSignature)
} else
publicSignature
}
override fun composeAccessorSignature(
@@ -118,12 +125,51 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat
isSetter: Boolean,
containingClass: ConeClassLikeLookupTag?
): IdSignature? {
val propertySignature = composeSignature(property, containingClass) as? IdSignature.CommonSignature ?: return null
val accessorFqName = if (isSetter) {
propertySignature.declarationFqName + ".<set-${property.name.asString()}>"
} else {
propertySignature.declarationFqName + ".<get-${property.name.asString()}>"
val propSig: IdSignature.CommonSignature
val fileSig: IdSignature.FileSignature?
when (val propertySignature = composeSignature(property, containingClass)) {
is IdSignature.CompositeSignature -> {
propSig = propertySignature.inner as? IdSignature.CommonSignature ?: return null
fileSig = propertySignature.container as? IdSignature.FileSignature ?: return null
}
is IdSignature.CommonSignature -> {
propSig = propertySignature
fileSig = null
}
else -> return null
}
return IdSignature.CommonSignature(propertySignature.packageFqName, accessorFqName, propertySignature.id, propertySignature.mask)
val id = with(mangler) {
if (isSetter) {
property.setterOrDefault().signatureMangle(compatibleMode = false)
} else {
property.getterOrDefault().signatureMangle(compatibleMode = false)
}
}
val accessorFqName = if (isSetter) {
propSig.declarationFqName + ".<set-${property.name.asString()}>"
} else {
propSig.declarationFqName + ".<get-${property.name.asString()}>"
}
val commonSig = IdSignature.CommonSignature(propSig.packageFqName, accessorFqName, id, propSig.mask)
val accessorSig = IdSignature.AccessorSignature(propSig, commonSig)
return if (fileSig != null) {
IdSignature.CompositeSignature(fileSig, accessorSig)
} else accessorSig
}
private fun isTopLevelPrivate(declaration: FirDeclaration, containingClass: ConeClassLikeLookupTag?): Boolean =
containingClass == null && declaration is FirMemberDeclaration && declaration.visibility == Visibilities.Private
private fun FirProperty.getterOrDefault() =
getter ?: FirDefaultPropertyGetter(
source = null,
moduleData, origin, returnTypeRef, visibility, symbol
)
private fun FirProperty.setterOrDefault() =
setter ?: FirDefaultPropertySetter(
source = null,
moduleData, origin, returnTypeRef, visibility, symbol
)
}
@@ -14,5 +14,13 @@ val FirCallableDeclaration.irName: Name
is FirConstructor -> SpecialNames.INIT
is FirSimpleFunction -> this.name
is FirVariable -> this.name
is FirPropertyAccessor -> {
val prefix = when {
isGetter -> "<get-"
isSetter -> "<set-"
else -> error("unknown property accessor kind $this")
}
Name.special(prefix + propertySymbol!!.fir.name + ">")
}
else -> SpecialNames.ANONYMOUS
}