Init enum entries whenever we access companion object or accessing valueOf
Fixes https://youtrack.jetbrains.com/issue/KT-43987 Fixes https://youtrack.jetbrains.com/issue/KT-43989
This commit is contained in:
@@ -304,7 +304,7 @@ private val enumSyntheticFunsLoweringPhase = makeDeclarationTransformerPhase(
|
||||
::EnumSyntheticFunctionsLowering,
|
||||
name = "EnumSyntheticFunctionsLowering",
|
||||
description = "Implement `valueOf` and `values`",
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase, enumClassCreateInitializerLoweringPhase)
|
||||
)
|
||||
|
||||
private val enumUsageLoweringPhase = makeBodyLoweringPhase(
|
||||
|
||||
+37
-16
@@ -410,7 +410,7 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
|
||||
val irClass = declaration.parentAsClass
|
||||
if (irClass.isInstantiableEnum) {
|
||||
// Create entry instance getters. These are used to lower `IrGetEnumValue`.
|
||||
val entryGetInstanceFun = createGetEntryInstanceFun(irClass, declaration, irClass.initEntryInstancesFun!!)
|
||||
val entryGetInstanceFun = createGetEntryInstanceFun(irClass, declaration)
|
||||
|
||||
// TODO prettify
|
||||
entryGetInstanceFun.parent = irClass.parent
|
||||
@@ -426,7 +426,7 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
|
||||
}
|
||||
|
||||
private fun createGetEntryInstanceFun(
|
||||
irClass: IrClass, enumEntry: IrEnumEntry, initEntryInstancesFun: IrSimpleFunction
|
||||
irClass: IrClass, enumEntry: IrEnumEntry
|
||||
): IrSimpleFunction =
|
||||
context.mapping.enumEntryToGetInstanceFun.getOrPut(enumEntry) {
|
||||
context.irFactory.buildFun {
|
||||
@@ -439,7 +439,7 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
|
||||
}.also {
|
||||
it.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||
statements += context.createIrBuilder(it.symbol).irBlockBody(it) {
|
||||
+irCall(initEntryInstancesFun)
|
||||
+irCall(irClass.initEntryInstancesFun!!)
|
||||
+irReturn(irGetField(null, enumEntry.correspondingField!!))
|
||||
}.statements
|
||||
}
|
||||
@@ -449,20 +449,40 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
|
||||
private val IrClass.isInstantiableEnum: Boolean
|
||||
get() = isEnumClass && !isExpect && !isEffectivelyExternal()
|
||||
|
||||
private val IrDeclaration.parentEnumClassOrNull: IrClass?
|
||||
get() = parents.filterIsInstance<IrClass>().firstOrNull { it.isInstantiableEnum }
|
||||
|
||||
class EnumSyntheticFunctionsLowering(val context: JsCommonBackendContext) : DeclarationTransformer {
|
||||
|
||||
private var IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun
|
||||
private val IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun
|
||||
private val IrClass.initEntryInstancesFun: IrSimpleFunction? by context.mapping.enumClassToInitEntryInstancesFun
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (declaration is IrConstructor && declaration.isPrimary) {
|
||||
declaration.parentEnumClassOrNull?.let { enumClass ->
|
||||
if (declaration.parentClassOrNull?.isCompanion == true) {
|
||||
(declaration.body as? IrSyntheticBody)?.let { originalBody ->
|
||||
declaration.parentEnumClassOrNull?.let { enumClass ->
|
||||
declaration.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||
statements += context.createIrBuilder(declaration.symbol).irBlockBody {
|
||||
+irCall(enumClass.initEntryInstancesFun!!.symbol)
|
||||
}.statements + originalBody.statements
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is IrSimpleFunction) {
|
||||
(declaration.body as? IrSyntheticBody)?.let { body ->
|
||||
val kind = body.kind
|
||||
|
||||
declaration.parents.filterIsInstance<IrClass>().firstOrNull { it.isInstantiableEnum }?.let { irClass ->
|
||||
declaration.parentEnumClassOrNull?.let { enumClass ->
|
||||
declaration.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||
statements += when (kind) {
|
||||
IrSyntheticBodyKind.ENUM_VALUES -> createEnumValuesBody(declaration, irClass)
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF -> createEnumValueOfBody(declaration, irClass)
|
||||
IrSyntheticBodyKind.ENUM_VALUES -> createEnumValuesBody(declaration, enumClass)
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF -> createEnumValueOfBody(declaration, enumClass)
|
||||
}.statements
|
||||
}
|
||||
}
|
||||
@@ -479,15 +499,16 @@ class EnumSyntheticFunctionsLowering(val context: JsCommonBackendContext) : Decl
|
||||
|
||||
return context.createIrBuilder(valueOfFun.symbol).run {
|
||||
irBlockBody {
|
||||
+irReturn(
|
||||
irWhen(
|
||||
irClass.defaultType,
|
||||
irClass.enumEntries.map {
|
||||
irBranch(
|
||||
irEquals(irString(it.name.identifier), irGet(nameParameter)), irCall(it.getInstanceFun!!)
|
||||
)
|
||||
} + irElseBranch(irCall(throwISESymbol))
|
||||
)
|
||||
+irWhen(
|
||||
irClass.defaultType,
|
||||
irClass.enumEntries.map {
|
||||
irBranch(
|
||||
irEquals(irString(it.name.identifier), irGet(nameParameter)), irReturn(irCall(it.getInstanceFun!!))
|
||||
)
|
||||
} + irElseBranch(irBlock {
|
||||
+irCall(irClass.initEntryInstancesFun!!)
|
||||
+irCall(throwISESymbol)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user