[SLC] SymbolLightClassForEnumEntry: shouldn't be regular class

^KTIJ-23842 Fixed
This commit is contained in:
Dmitrii Gridin
2022-12-06 12:36:58 +01:00
committed by Space Team
parent 2405dd2c5c
commit cc9beb466e
4 changed files with 80 additions and 59 deletions
@@ -11,7 +11,6 @@ import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
@@ -27,12 +26,8 @@ import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForObject
import org.jetbrains.kotlin.light.classes.symbol.isConst
import org.jetbrains.kotlin.light.classes.symbol.isLateInit
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightSimpleMethod
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -263,45 +258,6 @@ internal open class SymbolLightClassForClassOrObject : SymbolLightClassForNamedC
}
}
context(KtAnalysisSession)
protected fun addPropertyBackingFields(result: MutableList<KtLightField>, symbolWithMembers: KtSymbolWithMembers) {
val propertySymbols = symbolWithMembers.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.applyIf(isCompanionObject) {
// All fields for companion object of classes are generated to the containing class
// For interfaces, only @JvmField-annotated properties are generated to the containing class
// Probably, the same should work for const vals but it doesn't at the moment (see KT-28294)
filter { containingClass?.isInterface == true && !it.hasJvmFieldAnnotation() }
}
val propertyGroups = propertySymbols.groupBy { it.isFromPrimaryConstructor }
val nameGenerator = SymbolLightField.FieldNameGenerator()
fun addPropertyBackingField(propertySymbol: KtPropertySymbol) {
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
val isLateInit = propertySymbol.isLateInit
val isConst = propertySymbol.isConst
val forceStatic = isObject
val takePropertyVisibility = isLateInit || isJvmField || isConst
createField(
declaration = propertySymbol,
nameGenerator = nameGenerator,
isTopLevel = false,
forceStatic = forceStatic,
takePropertyVisibility = takePropertyVisibility,
result = result
)
}
// First, properties from parameters
propertyGroups[true]?.forEach(::addPropertyBackingField)
// Then, regular member properties
propertyGroups[false]?.forEach(::addPropertyBackingField)
}
context(KtAnalysisSession)
private fun addInstanceFieldIfNeeded(result: MutableList<KtLightField>, namedClassOrObjectSymbol: KtNamedClassOrObjectSymbol) {
if (!isNamedObject || isLocal) return
@@ -11,19 +11,19 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.light.classes.symbol.codeReferences.SymbolLightPsiJavaCodeReferenceElementWithNoReference
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtEnumEntry
internal class SymbolLightClassForEnumEntry(
private val enumConstant: SymbolLightFieldForEnumEntry,
private val enumClass: SymbolLightClassForClassOrObject,
ktModule: KtModule,
) : SymbolLightClassForClassOrObject(
enumConstant.kotlinOrigin,
ktModule,
), PsiEnumConstantInitializer {
) : SymbolLightClassBase(ktModule, enumConstant.manager), PsiEnumConstantInitializer {
override fun getBaseClassType(): PsiClassType = enumConstant.type as PsiClassType //???TODO
override fun getBaseClassReference(): PsiJavaCodeReferenceElement =
@@ -85,10 +85,11 @@ internal class SymbolLightClassForEnumEntry(
override fun getSuperClass(): PsiClass = enumClass
override fun getInterfaces(): Array<PsiClass> = PsiClass.EMPTY_ARRAY
override fun getSupers(): Array<PsiClass> = arrayOf(enumClass)
override fun getSuperTypes(): Array<PsiClassType> = arrayOf(baseClassType)
override fun getParent(): PsiElement? = containingClass
override fun getParent(): PsiElement = containingClass
override fun getScope(): PsiElement? = parent
override fun getScope(): PsiElement = parent
private val _ownFields: List<KtLightField> by lazyPub {
enumConstant.withEnumEntrySymbol { enumEntrySymbol ->
@@ -110,9 +111,7 @@ internal class SymbolLightClassForEnumEntry(
val declaredMemberScope = enumEntrySymbol.getDeclaredMemberScope()
val visibleDeclarations = declaredMemberScope.getCallableSymbols()
val suppressStatic = isCompanionObject
createMethods(visibleDeclarations, result, suppressStatic = suppressStatic)
createMethods(visibleDeclarations, result)
createConstructors(declaredMemberScope.getConstructors(), result)
result
@@ -121,4 +120,25 @@ internal class SymbolLightClassForEnumEntry(
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods
override fun getOwnInnerClasses(): MutableList<PsiClass> = mutableListOf()
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (!checkDeep) return baseClass == enumClass
return super.isInheritor(baseClass, checkDeep = true)
}
private val _identifier: PsiIdentifier by lazyPub {
KtLightIdentifier(this, kotlinOrigin)
}
// probably should be dropped after KT-54798
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun getName(): String? = kotlinOrigin.name
override fun isDeprecated(): Boolean = false
override fun isInterface(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = false
override val kotlinOrigin: KtEnumEntry get() = enumConstant.kotlinOrigin
override val originKind: LightClassOriginKind = LightClassOriginKind.SOURCE
override fun isValid(): Boolean = enumConstant.isValid
}
@@ -35,6 +35,8 @@ import org.jetbrains.kotlin.light.classes.symbol.copy
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty
import org.jetbrains.kotlin.light.classes.symbol.isConst
import org.jetbrains.kotlin.light.classes.symbol.isLateInit
import org.jetbrains.kotlin.light.classes.symbol.mapType
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightAccessorMethod
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightConstructor
@@ -46,6 +48,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import java.util.*
internal fun createSymbolLightClassNoCache(classOrObject: KtClassOrObject, ktModule: KtModule): KtLightClass? = when {
@@ -101,7 +104,7 @@ private fun lightClassForEnumEntry(ktEnumEntry: KtEnumEntry): KtLightClass? {
}
context(KtAnalysisSession)
internal fun SymbolLightClassForClassLike<*>.createConstructors(
internal fun SymbolLightClassBase.createConstructors(
declarations: Sequence<KtConstructorSymbol>,
result: MutableList<KtLightMethod>,
) {
@@ -156,10 +159,10 @@ private fun SymbolLightClassBase.shouldGenerateNoArgOverload(
!primaryConstructor.hasJvmOverloadsAnnotation()
}
private fun SymbolLightClassForClassLike<*>.defaultConstructor(): KtLightMethod {
private fun SymbolLightClassBase.defaultConstructor(): KtLightMethod {
val classOrObject = kotlinOrigin
val visibility = when {
isObject || isEnum -> PsiModifier.PRIVATE
this is SymbolLightClassForClassLike<*> && (isObject || isEnum) -> PsiModifier.PRIVATE
classOrObject?.hasModifier(SEALED_KEYWORD) == true -> PsiModifier.PROTECTED
this is SymbolLightClassForEnumEntry -> PsiModifier.PACKAGE_LOCAL
else -> PsiModifier.PUBLIC
@@ -168,7 +171,7 @@ private fun SymbolLightClassForClassLike<*>.defaultConstructor(): KtLightMethod
return noArgConstructor(visibility, METHOD_INDEX_FOR_DEFAULT_CTOR)
}
private fun SymbolLightClassForClassLike<*>.noArgConstructor(
private fun SymbolLightClassBase.noArgConstructor(
visibility: String,
methodIndex: Int,
): KtLightMethod = SymbolLightNoArgConstructor(
@@ -516,3 +519,45 @@ internal fun KtClassOrObject.checkIsInheritor(superClassOrigin: KtClassOrObject,
private val KtSymbolWithTypeParameters.hasReifiedParameters: Boolean
get() = typeParameters.any { it.isReified }
context(KtAnalysisSession)
internal fun SymbolLightClassBase.addPropertyBackingFields(
result: MutableList<KtLightField>,
symbolWithMembers: KtSymbolWithMembers,
) {
val propertySymbols = symbolWithMembers.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtPropertySymbol>()
.applyIf(symbolWithMembers is KtClassOrObjectSymbol && symbolWithMembers.classKind == KtClassKind.COMPANION_OBJECT) {
// All fields for companion object of classes are generated to the containing class
// For interfaces, only @JvmField-annotated properties are generated to the containing class
// Probably, the same should work for const vals but it doesn't at the moment (see KT-28294)
filter { containingClass?.isInterface == true && !it.hasJvmFieldAnnotation() }
}
val propertyGroups = propertySymbols.groupBy { it.isFromPrimaryConstructor }
val nameGenerator = SymbolLightField.FieldNameGenerator()
val forceStatic = symbolWithMembers is KtClassOrObjectSymbol && symbolWithMembers.classKind.isObject
fun addPropertyBackingField(propertySymbol: KtPropertySymbol) {
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
val isLateInit = propertySymbol.isLateInit
val isConst = propertySymbol.isConst
val takePropertyVisibility = isLateInit || isJvmField || isConst
createField(
declaration = propertySymbol,
nameGenerator = nameGenerator,
isTopLevel = false,
forceStatic = forceStatic,
takePropertyVisibility = takePropertyVisibility,
result = result
)
}
// First, properties from parameters
propertyGroups[true]?.forEach(::addPropertyBackingField)
// Then, regular member properties
propertyGroups[false]?.forEach(::addPropertyBackingField)
}
@@ -9,13 +9,13 @@ import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassLike
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList
internal class SymbolLightNoArgConstructor(
lightMemberOrigin: LightMemberOrigin?,
containingClass: SymbolLightClassForClassLike<*>,
containingClass: SymbolLightClassBase,
private val visibility: String,
methodIndex: Int,
) : SymbolLightMethodBase(lightMemberOrigin, containingClass, methodIndex) {