FIR: serialize correct fqnames for local classes

This commit is contained in:
pyos
2020-12-04 12:05:27 +01:00
committed by Mikhail Glukhikh
parent 12f936f6b7
commit 41f56729f9
12 changed files with 65 additions and 24 deletions
@@ -391,7 +391,7 @@ object KotlinToJVMBytecodeCompiler {
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent)
FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
}
CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done()
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.serialization
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.metadata.serialization.StringTable
@@ -16,11 +17,11 @@ interface FirElementAwareStringTable : StringTable {
fun getFqNameIndex(classLikeDeclaration: FirClassLikeDeclaration<*>): Int {
val classId = classLikeDeclaration.symbol.classId.takeIf { !it.isLocal }
?: getLocalClassIdReplacement(classLikeDeclaration)
?: getLocalClassIdReplacement(classLikeDeclaration as FirClass<*>)
?: throw IllegalStateException("Cannot get FQ name of local class: ${classLikeDeclaration.render()}")
return getQualifiedClassNameIndex(classId)
}
fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId? = null
fun getLocalClassIdReplacement(firClass: FirClass<*>): ClassId? = null
}
@@ -5,30 +5,32 @@
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper
import org.jetbrains.kotlin.backend.jvm.codegen.mapClass
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.serialization.FirElementAwareStringTable
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
class FirJvmElementAwareStringTable(
private val typeMapper: IrTypeMapper,
private val components: Fir2IrComponents,
nameResolver: JvmNameResolver? = null
) : JvmStringTable(nameResolver), FirElementAwareStringTable {
override fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId {
return when (classLikeDeclaration.symbol.classId.outerClassId) {
// TODO: how to determine parent declaration for FIR local class properly?
//is ClassifierDescriptorWithTypeParameters -> getLocalClassIdReplacement(container).createNestedClassId(descriptor.name)
// null -> {
// throw IllegalStateException(
// "getLocalClassIdReplacement should only be called for local classes: ${classLikeDeclaration.render()}"
// )
// }
override fun getLocalClassIdReplacement(firClass: FirClass<*>): ClassId =
components.classifierStorage.getCachedIrClass(firClass)?.getLocalClassIdReplacement()
?: throw AssertionError("not a local class: ${firClass.symbol.classId}")
private fun IrClass.getLocalClassIdReplacement(): ClassId =
when (val parent = parent) {
is IrClass -> parent.getLocalClassIdReplacement().createNestedClassId(name)
else -> {
classLikeDeclaration.symbol.classId
// TODO: typeMapper.mapClass
//val fqName = FqName(typeMapper.mapClass(descriptor).internalName.replace('/', '.'))
//ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
val fqName = FqName(typeMapper.mapClass(this).internalName.replace('/', '.'))
ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
}
}
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.backend.jvm
import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.codegen.state.GenerationState
@@ -12,6 +13,7 @@ import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.firProvider
@@ -41,10 +43,12 @@ class FirJvmSerializerExtension(
state: GenerationState,
private val irClass: IrClass,
private val localDelegatedProperties: List<FirProperty>,
private val approximator: AbstractTypeApproximator
private val approximator: AbstractTypeApproximator,
typeMapper: IrTypeMapper,
components: Fir2IrComponents
) : FirSerializerExtension() {
private val globalBindings = state.globalSerializationBindings
override val stringTable = FirJvmElementAwareStringTable()
override val stringTable = FirJvmElementAwareStringTable(typeMapper, components)
private val useTypeTable = state.useTypeTableInSerializer
private val moduleName = state.moduleName
private val classBuilderMode = state.classBuilderMode
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
@@ -39,6 +40,7 @@ class FirMetadataSerializer(
private val context: JvmBackendContext,
private val irClass: IrClass,
private val serializationBindings: JvmSerializationBindings,
components: Fir2IrComponents,
parent: MetadataSerializer?
) : MetadataSerializer {
private val approximator = object : AbstractTypeApproximator(session.typeContext) {
@@ -144,8 +146,10 @@ class FirMetadataSerializer(
(it.owner.metadata as FirMetadataSource.Property).fir.copyToFreeProperty()
} ?: emptyList()
private val serializerExtension =
FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator)
private val serializerExtension = FirJvmSerializerExtension(
session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator,
context.typeMapper, components
)
private val serializer: FirElementSerializer? =
when (val metadata = irClass.metadata) {
@@ -135,7 +135,7 @@ class Fir2IrClassifierStorage(
return this
}
internal fun getCachedIrClass(klass: FirClass<*>): IrClass? {
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.Local) {
localStorage.getLocalClass(klass)
} else {
@@ -28465,6 +28465,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt");
}
@TestMetadata("withLocalType.kt")
public void testWithLocalType() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt");
}
@TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JVM
// WITH_REFLECT
// WITH_RUNTIME
import kotlin.reflect.full.declaredMemberProperties
fun box(): String {
class A(val x: String)
class B(val y: A)
return (B::class.declaredMemberProperties.single().invoke(B(A("OK"))) as A).x
}
@@ -144,7 +144,7 @@ object GenerationUtils {
codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent)
FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
}
generationState.factory.done()
@@ -28831,6 +28831,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt");
}
@TestMetadata("withLocalType.kt")
public void testWithLocalType() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt");
}
@TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -26465,6 +26465,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt");
}
@TestMetadata("withLocalType.kt")
public void testWithLocalType() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt");
}
@TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -28465,6 +28465,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt");
}
@TestMetadata("withLocalType.kt")
public void testWithLocalType() throws Exception {
runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt");
}
@TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)