KT-29340 Provide effective modality for enum class in IR

* if enum class has abstract members, then it is ABSTRACT
* otherwise, if enum class has entries with members, then it is OPEN
* otherwise, it is FINAL.
This commit is contained in:
Dmitry Petrov
2019-01-21 12:53:13 +03:00
parent efdb4e1d5d
commit 360bfcaf6a
16 changed files with 776 additions and 39 deletions
@@ -58,7 +58,8 @@ class ClassGenerator(
val endOffset = ktClassOrObject.pureEndOffset
return context.symbolTable.declareClass(
startOffset, endOffset, IrDeclarationOrigin.DEFINED, classDescriptor
startOffset, endOffset, IrDeclarationOrigin.DEFINED, classDescriptor,
getEffectiveModality(ktClassOrObject, classDescriptor)
).buildWithScope { irClass ->
declarationGenerator.generateGlobalTypeParametersDeclarations(irClass, classDescriptor.declaredTypeParameters)
@@ -99,6 +100,25 @@ class ClassGenerator(
}
}
private fun getEffectiveModality(ktClassOrObject: KtPureClassOrObject, classDescriptor: ClassDescriptor): Modality =
when {
!DescriptorUtils.isEnumClass(classDescriptor) ->
classDescriptor.modality
DescriptorUtils.hasAbstractMembers(classDescriptor) ->
Modality.ABSTRACT
ktClassOrObject.hasEnumEntriesWithClassMembers() ->
Modality.OPEN
else ->
Modality.FINAL
}
private fun KtPureClassOrObject.hasEnumEntriesWithClassMembers(): Boolean {
val body = this.body ?: return false
return body.enumEntries.any { it.hasMemberDeclarations() }
}
private fun KtEnumEntry.hasMemberDeclarations() = declarations.isNotEmpty()
private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtPureClassOrObject) {
irClass.descriptor.unsubstitutedMemberScope.getContributedDescriptors()
.mapNotNull {
@@ -252,20 +272,20 @@ class ClassGenerator(
val dispatchReceiverParameter = irDelegatedFunction.dispatchReceiverParameter!!
val dispatchReceiverType = dispatchReceiverParameter.type
irCall.dispatchReceiver =
IrGetFieldImpl(
IrGetFieldImpl(
startOffset, endOffset,
irDelegate.symbol,
irDelegate.type,
IrGetValueImpl(
startOffset, endOffset,
irDelegate.symbol,
irDelegate.type,
IrGetValueImpl(
startOffset, endOffset,
dispatchReceiverType,
dispatchReceiverParameter.symbol
)
dispatchReceiverType,
dispatchReceiverParameter.symbol
)
)
irCall.extensionReceiver =
irDelegatedFunction.extensionReceiverParameter?.let { extensionReceiver ->
IrGetValueImpl(startOffset, endOffset, extensionReceiver.type, extensionReceiver.symbol)
}
irDelegatedFunction.extensionReceiverParameter?.let { extensionReceiver ->
IrGetValueImpl(startOffset, endOffset, extensionReceiver.type, extensionReceiver.symbol)
}
irCall.mapValueParameters { overriddenValueParameter ->
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
val irDelegatedValueParameter = irDelegatedFunction.getIrValueParameter(delegatedValueParameter)
@@ -400,11 +420,11 @@ class ClassGenerator(
if (!enumEntryDescriptor.isExpect) {
irEnumEntry.initializerExpression =
createBodyGenerator(irEnumEntry.symbol)
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
createBodyGenerator(irEnumEntry.symbol)
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
}
if (ktEnumEntry.declarations.isNotEmpty()) {
if (ktEnumEntry.hasMemberDeclarations()) {
irEnumEntry.correspondingClass = generateClass(ktEnumEntry)
}
}