LC: rework modality of enum class

It is abstract if it has abstract member.
It is final if it doesn't have enum entries that need subclass.
Otherwise, it is open (i.e., no modifier)

^KT-57567 Fixed
This commit is contained in:
Jinseong Jeon
2023-06-15 19:23:22 -07:00
committed by Ilya Kirillov
parent 7930885131
commit 7f1424737e
7 changed files with 55 additions and 11 deletions
@@ -15,10 +15,14 @@ import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.resolve.DescriptorUtils
// light class for top level or (inner/nested of top level) source declarations
@@ -69,7 +73,7 @@ abstract class KtLightClassImpl(
protected open fun computeIsFinal(): Boolean = when {
classOrObject.hasModifier(KtTokens.FINAL_KEYWORD) -> true
isAbstract() || isSealed() -> false
isEnum -> false
isEnum -> !hasEnumEntryWhichRequiresSubclass()
!classOrObject.hasModifier(KtTokens.OPEN_KEYWORD) -> {
val descriptor = lazy { getDescriptor() }
var modifier = PsiModifier.FINAL
@@ -83,7 +87,21 @@ abstract class KtLightClassImpl(
else -> false
}
private fun isAbstract(): Boolean = classOrObject.hasModifier(KtTokens.ABSTRACT_KEYWORD) || isInterface
private fun hasEnumEntryWhichRequiresSubclass(): Boolean {
return classOrObject.declarations.any { declaration ->
declaration is KtEnumEntry && declaration.declarations.any { it !is KtConstructor<*> }
}
}
private fun isAbstract(): Boolean =
classOrObject.hasModifier(KtTokens.ABSTRACT_KEYWORD) || isInterface || (isEnum && hasAbstractMember())
private fun hasAbstractMember(): Boolean {
val descriptor = getDescriptor() ?: return false
return descriptor.unsubstitutedMemberScope.getContributedDescriptors().any {
(it as? MemberDescriptor)?.modality == Modality.ABSTRACT
}
}
private fun isSealed(): Boolean = classOrObject.hasModifier(KtTokens.SEALED_KEYWORD)