FIR2IR: don't create synthetic class for enum entry w/o members

This commit is contained in:
Jinseong Jeon
2020-07-12 10:30:48 +03:00
committed by Mikhail Glukhikh
parent 2ea3579281
commit 1a861b2df9
11 changed files with 85 additions and 805 deletions
@@ -135,7 +135,7 @@ class FirElementSerializer private constructor(
?: klass.declarations.filterIsInstance<FirCallableMemberDeclaration<*>>()
for (declaration in callableMembers) {
if (declaration.isStatic) continue // ??? Miss values() & valueOf()
if (declaration !is FirEnumEntry && declaration.isStatic) continue // ??? Miss values() & valueOf()
when (declaration) {
is FirProperty -> propertyProto(declaration)?.let { builder.addProperty(it) }
is FirSimpleFunction -> functionProto(declaration)?.let { builder.addFunction(it) }
@@ -396,11 +396,14 @@ class Fir2IrClassifierStorage(
this.parent = irParent
}
val initializer = enumEntry.initializer
if (initializer != null) {
initializer as FirAnonymousObject
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
this.correspondingClass = klass
if (initializer is FirAnonymousObject) {
// An enum entry with its own members
if (initializer.declarations.any { it !is FirConstructor }) {
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
this.correspondingClass = klass
}
// Otherwise, this is a default-ish enum entry whose initializer would be a delegating constructor call,
// which will be translated via visitor later.
} else if (irParent != null && origin == IrDeclarationOrigin.DEFINED) {
val constructor = irParent.constructors.first()
this.initializerExpression = IrExpressionBodyImpl(
@@ -106,26 +106,40 @@ class Fir2IrVisitor(
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement {
val irEnumEntry = classifierStorage.getCachedIrEnumEntry(enumEntry)!!
val correspondingClass = irEnumEntry.correspondingClass ?: return irEnumEntry
declarationStorage.enterScope(irEnumEntry)
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
val anonymousObject = enumEntry.initializer as FirAnonymousObject
converter.processAnonymousObjectMembers(anonymousObject, correspondingClass)
conversionScope.withParent(correspondingClass) {
conversionScope.withContainingFirClass(anonymousObject) {
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
}
val constructor = correspondingClass.constructors.first()
irEnumEntry.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(
startOffset, endOffset, enumEntry.returnTypeRef.toIrType(),
constructor.symbol,
typeArgumentsCount = constructor.typeParameters.size,
valueArgumentsCount = constructor.valueParameters.size
val correspondingClass = irEnumEntry.correspondingClass
val initializer = enumEntry.initializer
// If then enum entry has its own members, we need to introduce a synthetic class.
if (correspondingClass != null) {
declarationStorage.enterScope(irEnumEntry)
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
val anonymousObject = enumEntry.initializer as FirAnonymousObject
converter.processAnonymousObjectMembers(anonymousObject, correspondingClass)
conversionScope.withParent(correspondingClass) {
conversionScope.withContainingFirClass(anonymousObject) {
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
}
val constructor = correspondingClass.constructors.first()
irEnumEntry.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(
startOffset, endOffset, enumEntry.returnTypeRef.toIrType(),
constructor.symbol,
typeArgumentsCount = constructor.typeParameters.size,
valueArgumentsCount = constructor.valueParameters.size
)
)
)
}
declarationStorage.leaveScope(irEnumEntry)
} else if (initializer is FirAnonymousObject) {
// Otherwise, this is a default-ish enum entry, which doesn't need its own synthetic class.
// During raw FIR building, we put the delegated constructor call inside an anonymous object.
val primaryConstructor = initializer.getPrimaryConstructorIfAny()
val delegatedConstructor = primaryConstructor?.delegatedConstructor
if (delegatedConstructor != null) {
with(memberGenerator) {
irEnumEntry.initializerExpression = IrExpressionBodyImpl(delegatedConstructor.toIrDelegatingConstructorCall())
}
}
}
declarationStorage.leaveScope(irEnumEntry)
return irEnumEntry
}
@@ -272,7 +272,7 @@ internal class ClassMemberGenerator(
return this
}
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpression {
internal fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpression {
val constructedIrType = constructedTypeRef.toIrType()
val referencedSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
?: return convertWithOffsets { startOffset, endOffset ->