org.jetbrains.kotlin.fir.backend.jvm.FirJvmElementAwareStringTable.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.serialization.FirElementAwareStringTable
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
class FirJvmElementAwareStringTable(
private val typeMapper: IrTypeMapper,
private val components: Fir2IrComponents,
private val localPoppedUpClasses: List,
nameResolver: JvmNameResolver? = null
) : JvmStringTable(nameResolver), FirElementAwareStringTable {
override fun getLocalClassIdReplacement(firClass: FirClass): ClassId {
if (components.configuration.skipBodies) {
return firClass.superConeTypes.firstOrNull()?.lookupTag?.classId ?: StandardClassIds.Any
}
// TODO: should call getCachedIrLocalClass, see KT-66018
return components.classifierStorage.getIrClass(firClass).getLocalClassIdReplacement()
}
private fun IrClass.getLocalClassIdReplacement(): ClassId {
// This convoluted implementation aims to reproduce K1 behaviour (see JvmCodegenStringTable::getLocalClassIdReplacement).
// K1 uses both '.' and '$' to separate nested class names when serializing metadata.
// That does not make much sense and looks like an artifact of implementation arising from K1 descriptors structure.
// But we still need to preserve it to establish compatibility with K2-produced metadata.
val thisClassName = typeMapper.classInternalName(this).replace('/', '.')
if (attributeOwnerId in localPoppedUpClasses) {
// For those classes, whose original parent has been changed on the lowering stage.
// In K1, the `containingDeclaration` of such class descriptor would be the original declaration: constructor or property.
// Thus, this case corresponds to the `else` branch of JvmCodegenStringTable::getLocalClassIdReplacement.
val thisClassFqName = FqName(thisClassName)
return ClassId(thisClassFqName.parent(), FqName.topLevel(thisClassFqName.shortName()), isLocal = true)
} else {
// Otherwise, find topmost class parent. Its name will have '$' as delimiter
val topmostClassParent = generateSequence(this) { it.parent as? IrClass }.last()
val topmostClassParentName = typeMapper.classInternalName(topmostClassParent).replace('/', '.')
val prefixFqName = FqName(topmostClassParentName)
var classId = ClassId(prefixFqName.parent(), FqName.topLevel(prefixFqName.shortName()), isLocal = true)
if (thisClassName.length == topmostClassParentName.length) return classId
// The remaining part uses '.'
thisClassName.substring(topmostClassParentName.length + 1).split('$').forEach {
classId = classId.createNestedClassId(Name.identifier(it))
}
return classId
}
}
}