Psi2Ir: Create instance initializer calls in enum class constructors

This commit is contained in:
Steven Schäfer
2020-01-09 14:03:42 +01:00
committed by max-kammerer
parent 83edc7fa73
commit f8779ddf9d
3 changed files with 8 additions and 64 deletions
@@ -125,9 +125,6 @@ class EnumClassConstructorTransformer(val context: CommonBackendContext, private
private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>() private val loweredEnumConstructors = HashMap<IrConstructorSymbol, IrConstructor>()
fun transform(): List<IrDeclaration> { fun transform(): List<IrDeclaration> {
// Make sure InstanceInitializer exists
insertInstanceInitializer()
// Add `name` and `ordinal` parameters to enum class constructors // Add `name` and `ordinal` parameters to enum class constructors
lowerEnumConstructorsSignature() lowerEnumConstructorsSignature()
@@ -149,33 +146,6 @@ class EnumClassConstructorTransformer(val context: CommonBackendContext, private
return listOf(irClass) return listOf(irClass)
} }
private fun insertInstanceInitializer() {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass) = declaration
override fun visitConstructor(declaration: IrConstructor): IrStatement {
declaration.transformChildrenVoid(this)
val blockBody = declaration.body as IrBlockBody
if (!blockBody.statements.any { it is IrInstanceInitializerCall }) {
blockBody.statements.transformFlat {
if (it is IrEnumConstructorCall)
listOf(
it, IrInstanceInitializerCallImpl(
declaration.startOffset, declaration.startOffset,
irClass.symbol, context.irBuiltIns.unitType
)
)
else null
}
}
return declaration
}
})
}
private fun lowerEnumConstructorsSignature() { private fun lowerEnumConstructorsSignature() {
irClass.declarations.transform { declaration -> irClass.declarations.transform { declaration ->
if (declaration is IrConstructor) { if (declaration is IrConstructor) {
@@ -69,7 +69,6 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP
private lateinit var valueOfFunction: IrFunction private lateinit var valueOfFunction: IrFunction
fun run() { fun run() {
insertInstanceInitializer()
assignOrdinalsToEnumEntries() assignOrdinalsToEnumEntries()
lowerEnumConstructors(irClass) lowerEnumConstructors(irClass)
lowerEnumEntries() lowerEnumEntries()
@@ -77,35 +76,6 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP
lowerEnumClassBody() lowerEnumClassBody()
} }
// Make sure that an instance initializer call exists, so that field initialization code will be generated.
// TODO: This function is identical to the one used in the JS lowerings. Share them.
private fun insertInstanceInitializer() {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass) = declaration
override fun visitConstructor(declaration: IrConstructor): IrStatement {
declaration.transformChildrenVoid(this)
val blockBody = declaration.body as IrBlockBody
if (!blockBody.statements.any { it is IrInstanceInitializerCall }) {
blockBody.statements.transformFlat {
if (it is IrEnumConstructorCall)
listOf(
it, IrInstanceInitializerCallImpl(
declaration.startOffset, declaration.startOffset,
irClass.symbol, context.irBuiltIns.unitType
)
)
else null
}
}
return declaration
}
})
}
private fun assignOrdinalsToEnumEntries() { private fun assignOrdinalsToEnumEntries() {
var ordinal = 0 var ordinal = 0
irClass.declarations.forEach { irClass.declarations.forEach {
@@ -54,11 +54,15 @@ fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean {
} }
fun KtSecondaryConstructor.isConstructorDelegatingToSuper(bindingContext: BindingContext): Boolean { fun KtSecondaryConstructor.isConstructorDelegatingToSuper(bindingContext: BindingContext): Boolean {
val delegatingResolvedCall = getDelegationCall().getResolvedCall(bindingContext) ?: return false
val constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, this) ?: return false val constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, this) ?: return false
val ownerClassDescriptor = constructorDescriptor.containingDeclaration val delegatingResolvedCall = getDelegationCall().getResolvedCall(bindingContext)
val targetClassDescriptor = delegatingResolvedCall.resultingDescriptor.containingDeclaration return if (delegatingResolvedCall != null) {
return targetClassDescriptor != ownerClassDescriptor val ownerClassDescriptor = constructorDescriptor.containingDeclaration
val targetClassDescriptor = delegatingResolvedCall.resultingDescriptor.containingDeclaration
targetClassDescriptor != ownerClassDescriptor
} else {
constructorDescriptor.constructedClass.kind == ClassKind.ENUM_CLASS
}
} }
inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) = inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =