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( codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager, extensions generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent -> ) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent) FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
} }
CodegenFactory.doCheckCancelled(generationState) CodegenFactory.doCheckCancelled(generationState)
generationState.factory.done() generationState.factory.done()
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.serialization 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.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.metadata.serialization.StringTable import org.jetbrains.kotlin.metadata.serialization.StringTable
@@ -16,11 +17,11 @@ interface FirElementAwareStringTable : StringTable {
fun getFqNameIndex(classLikeDeclaration: FirClassLikeDeclaration<*>): Int { fun getFqNameIndex(classLikeDeclaration: FirClassLikeDeclaration<*>): Int {
val classId = classLikeDeclaration.symbol.classId.takeIf { !it.isLocal } 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()}") ?: throw IllegalStateException("Cannot get FQ name of local class: ${classLikeDeclaration.render()}")
return getQualifiedClassNameIndex(classId) 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 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.fir.serialization.FirElementAwareStringTable
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class FirJvmElementAwareStringTable( class FirJvmElementAwareStringTable(
private val typeMapper: IrTypeMapper,
private val components: Fir2IrComponents,
nameResolver: JvmNameResolver? = null nameResolver: JvmNameResolver? = null
) : JvmStringTable(nameResolver), FirElementAwareStringTable { ) : JvmStringTable(nameResolver), FirElementAwareStringTable {
override fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId { override fun getLocalClassIdReplacement(firClass: FirClass<*>): ClassId =
return when (classLikeDeclaration.symbol.classId.outerClassId) { components.classifierStorage.getCachedIrClass(firClass)?.getLocalClassIdReplacement()
// TODO: how to determine parent declaration for FIR local class properly? ?: throw AssertionError("not a local class: ${firClass.symbol.classId}")
//is ClassifierDescriptorWithTypeParameters -> getLocalClassIdReplacement(container).createNestedClassId(descriptor.name)
// null -> { private fun IrClass.getLocalClassIdReplacement(): ClassId =
// throw IllegalStateException( when (val parent = parent) {
// "getLocalClassIdReplacement should only be called for local classes: ${classLikeDeclaration.render()}" is IrClass -> parent.getLocalClassIdReplacement().createNestedClassId(name)
// )
// }
else -> { else -> {
classLikeDeclaration.symbol.classId val fqName = FqName(typeMapper.mapClass(this).internalName.replace('/', '.'))
// TODO: typeMapper.mapClass ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
//val fqName = FqName(typeMapper.mapClass(descriptor).internalName.replace('/', '.'))
//ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
} }
} }
}
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.backend.jvm 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.ClassBuilderMode
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.codegen.state.GenerationState 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.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession 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.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firProvider
@@ -41,10 +43,12 @@ class FirJvmSerializerExtension(
state: GenerationState, state: GenerationState,
private val irClass: IrClass, private val irClass: IrClass,
private val localDelegatedProperties: List<FirProperty>, private val localDelegatedProperties: List<FirProperty>,
private val approximator: AbstractTypeApproximator private val approximator: AbstractTypeApproximator,
typeMapper: IrTypeMapper,
components: Fir2IrComponents
) : FirSerializerExtension() { ) : FirSerializerExtension() {
private val globalBindings = state.globalSerializationBindings private val globalBindings = state.globalSerializationBindings
override val stringTable = FirJvmElementAwareStringTable() override val stringTable = FirJvmElementAwareStringTable(typeMapper, components)
private val useTypeTable = state.useTypeTableInSerializer private val useTypeTable = state.useTypeTableInSerializer
private val moduleName = state.moduleName private val moduleName = state.moduleName
private val classBuilderMode = state.classBuilderMode 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.backend.jvm.codegen.MetadataSerializer
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
import org.jetbrains.kotlin.fir.FirSession 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.backend.FirMetadataSource
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
@@ -39,6 +40,7 @@ class FirMetadataSerializer(
private val context: JvmBackendContext, private val context: JvmBackendContext,
private val irClass: IrClass, private val irClass: IrClass,
private val serializationBindings: JvmSerializationBindings, private val serializationBindings: JvmSerializationBindings,
components: Fir2IrComponents,
parent: MetadataSerializer? parent: MetadataSerializer?
) : MetadataSerializer { ) : MetadataSerializer {
private val approximator = object : AbstractTypeApproximator(session.typeContext) { private val approximator = object : AbstractTypeApproximator(session.typeContext) {
@@ -144,8 +146,10 @@ class FirMetadataSerializer(
(it.owner.metadata as FirMetadataSource.Property).fir.copyToFreeProperty() (it.owner.metadata as FirMetadataSource.Property).fir.copyToFreeProperty()
} ?: emptyList() } ?: emptyList()
private val serializerExtension = private val serializerExtension = FirJvmSerializerExtension(
FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator) session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator,
context.typeMapper, components
)
private val serializer: FirElementSerializer? = private val serializer: FirElementSerializer? =
when (val metadata = irClass.metadata) { when (val metadata = irClass.metadata) {
@@ -135,7 +135,7 @@ class Fir2IrClassifierStorage(
return this 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) { return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.Local) {
localStorage.getLocalClass(klass) localStorage.getLocalClass(klass)
} else { } else {
@@ -28465,6 +28465,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); 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") @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @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( codegenFactory.generateModuleInFrontendIRMode(
generationState, moduleFragment, symbolTable, sourceManager, extensions generationState, moduleFragment, symbolTable, sourceManager, extensions
) { context, irClass, _, serializationBindings, parent -> ) { context, irClass, _, serializationBindings, parent ->
FirMetadataSerializer(session, context, irClass, serializationBindings, parent) FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent)
} }
generationState.factory.done() generationState.factory.done()
@@ -28831,6 +28831,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); 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") @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -26465,6 +26465,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); 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") @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -28465,6 +28465,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); 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") @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)