diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescEnumEntrySymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescEnumEntrySymbol.kt index e6b8baa2f95..c311c3b23f4 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescEnumEntrySymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/KtFe10DescEnumEntrySymbol.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.api.descriptors.symbols.isEqualTo import org.jetbrains.kotlin.analysis.api.descriptors.symbols.pointers.KtFe10DescEnumEntrySymbolPointer import org.jetbrains.kotlin.analysis.api.descriptors.symbols.pointers.KtFe10NeverRestoringSymbolPointer import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntryInitializerSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer @@ -27,7 +28,7 @@ import org.jetbrains.kotlin.name.Name internal class KtFe10DescEnumEntrySymbol( override val descriptor: ClassDescriptor, override val analysisContext: Fe10AnalysisContext -) : KtEnumEntrySymbol(), KtFe10DescMemberSymbol { +) : KtEnumEntrySymbol(), KtEnumEntryInitializerSymbol, KtFe10DescMemberSymbol { private val enumDescriptor: ClassDescriptor get() = descriptor.containingDeclaration as ClassDescriptor @@ -50,6 +51,11 @@ internal class KtFe10DescEnumEntrySymbol( override val name: Name get() = withValidityAssertion { descriptor.name } + // There doesn't seem to be a way to determine if `descriptor` has a body or not, so we return an initializer even for enum entries + // without a body. + override val enumEntryInitializer: KtEnumEntryInitializerSymbol? + get() = this + context(KtAnalysisSession) override fun createPointer(): KtSymbolPointer = withValidityAssertion { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiEnumEntrySymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiEnumEntrySymbol.kt index 1b4746aebbb..a75bb55e13f 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiEnumEntrySymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiEnumEntrySymbol.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.calla import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.createErrorType import org.jetbrains.kotlin.analysis.api.descriptors.utils.cached import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntryInitializerSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer @@ -33,7 +34,7 @@ import org.jetbrains.kotlin.resolve.BindingContext internal class KtFe10PsiEnumEntrySymbol( override val psi: KtEnumEntry, override val analysisContext: Fe10AnalysisContext -) : KtEnumEntrySymbol(), KtFe10PsiSymbol { +) : KtEnumEntrySymbol(), KtEnumEntryInitializerSymbol, KtFe10PsiSymbol { override val descriptor: ClassDescriptor? by cached { val bindingContext = analysisContext.analyze(psi, AnalysisMode.PARTIAL) bindingContext[BindingContext.CLASS, psi] @@ -61,6 +62,9 @@ internal class KtFe10PsiEnumEntrySymbol( override val name: Name get() = withValidityAssertion { psi.nameAsSafeName } + override val enumEntryInitializer: KtEnumEntryInitializerSymbol? + get() = this.takeIf { psi.body != null } + context(KtAnalysisSession) override fun createPointer(): KtSymbolPointer = withValidityAssertion { KtPsiBasedSymbolPointer.createForSymbolFromSource(this) ?: KtFe10NeverRestoringSymbolPointer() diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirAnonymousObjectSymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirAnonymousObjectSymbol.kt index b4261cc57ec..2a0b77161a8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirAnonymousObjectSymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirAnonymousObjectSymbol.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.requireOwnerPointe import org.jetbrains.kotlin.analysis.api.fir.utils.cached import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousObjectSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntryInitializerSymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer @@ -25,7 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol internal class KtFirAnonymousObjectSymbol( override val firSymbol: FirAnonymousObjectSymbol, override val analysisSession: KtFirAnalysisSession, -) : KtAnonymousObjectSymbol(), KtFirSymbol { +) : KtAnonymousObjectSymbol(), KtEnumEntryInitializerSymbol, KtFirSymbol { override val psi: PsiElement? = withValidityAssertion { firSymbol.fir.getAllowedPsi() } override val annotationsList by cached { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntrySymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntrySymbol.kt index 981bd996e71..998b3a5f6a3 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntrySymbol.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntrySymbol.kt @@ -15,11 +15,15 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.KtFirEnumEntrySymb import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.requireOwnerPointer import org.jetbrains.kotlin.analysis.api.fir.utils.cached import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntryInitializerSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -41,6 +45,20 @@ internal class KtFirEnumEntrySymbol( override val callableIdIfNonLocal: CallableId? get() = withValidityAssertion { firSymbol.getCallableIdIfNonLocal() } + override val enumEntryInitializer: KtEnumEntryInitializerSymbol? by cached { + if (firSymbol.fir.initializer == null) { + return@cached null + } + + firSymbol.fir.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) + + val initializerExpression = firSymbol.fir.initializer + check(initializerExpression is FirAnonymousObjectExpression) { + "Unexpected enum entry initializer: ${initializerExpression?.javaClass}" + } + KtFirAnonymousObjectSymbol(initializerExpression.anonymousObject.symbol, analysisSession) + } + context(KtAnalysisSession) override fun createPointer(): KtSymbolPointer = withValidityAssertion { KtPsiBasedSymbolPointer.createForSymbolFromSource(this) ?: KtFirEnumEntrySymbolPointer(requireOwnerPointer(), firSymbol.name) diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/renderer/declarations/renderers/callables/KtEnumEntrySymbolRenderer.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/renderer/declarations/renderers/callables/KtEnumEntrySymbolRenderer.kt index 3beb20702f4..649607de43b 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/renderer/declarations/renderers/callables/KtEnumEntrySymbolRenderer.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/renderer/declarations/renderers/callables/KtEnumEntrySymbolRenderer.kt @@ -21,7 +21,7 @@ public interface KtEnumEntrySymbolRenderer { " ".separated( { renderAnnotationsModifiersAndContextReceivers(symbol, printer) }, { nameRenderer.renderName(symbol, printer) }, - { classifierBodyRenderer.renderBody(symbol, printer) }, + { symbol.enumEntryInitializer?.let { classifierBodyRenderer.renderBody(it, printer) } }, ) } } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtVariableLikeSymbol.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtVariableLikeSymbol.kt index f4104deb697..e0773c2268f 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtVariableLikeSymbol.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KtVariableLikeSymbol.kt @@ -91,10 +91,37 @@ public abstract class KtEnumEntrySymbol : KtVariableLikeSymbol(), KtSymbolWithKi //todo reduntant, remove public abstract val containingEnumClassIdIfNonLocal: ClassId? + /** + * Returns the enum entry's initializer, or `null` if the enum entry doesn't have a body. + */ + public abstract val enumEntryInitializer: KtEnumEntryInitializerSymbol? + context(KtAnalysisSession) abstract override fun createPointer(): KtSymbolPointer } +/** + * An initializer for enum entries with a body. The initializer may contain its own declarations (especially overrides of members declared + * by the enum class), and is [similar to an object declaration](https://kotlinlang.org/spec/declarations.html#enum-class-declaration). + * + * #### Example + * + * ```kotlin + * enum class E { + * // `A` is declared with an initializer. + * A { + * val x: Int = 5 + * }, + * + * // `B` has no initializer. + * B + * } + * ``` + * + * The initializer of `A` declares a member `x: Int`, which is inaccessible outside the initializer. Still, the corresponding + * [KtEnumEntryInitializerSymbol] can be used to get a declared member scope that contains `x`. + */ +public interface KtEnumEntryInitializerSymbol : KtSymbolWithMembers public sealed class KtVariableSymbol : KtVariableLikeSymbol() { public abstract val isVal: Boolean diff --git a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt index cca06181abd..91066dcd5dd 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt @@ -519,6 +519,7 @@ scopes: callableIdIfNonLocal: /E.A containingEnumClassIdIfNonLocal: E contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: A origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.descriptors.txt index b72a14f0041..fcc810112ec 100644 --- a/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.descriptors.txt @@ -3,6 +3,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: kotlin/LazyThreadSafetyMode.SYNCHRONIZED containingEnumClassIdIfNonLocal: kotlin/LazyThreadSafetyMode contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(kotlin/LazyThreadSafetyMode.SYNCHRONIZED) isExtension: false name: SYNCHRONIZED origin: LIBRARY diff --git a/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.txt b/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.txt index 46469abe022..24e88c85142 100644 --- a/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.txt +++ b/analysis/analysis-api/testData/symbols/symbolByFqName/enumEntry.txt @@ -3,6 +3,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: kotlin/LazyThreadSafetyMode.SYNCHRONIZED containingEnumClassIdIfNonLocal: kotlin/LazyThreadSafetyMode contextReceivers: [] + enumEntryInitializer: null isExtension: false name: SYNCHRONIZED origin: LIBRARY diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enum.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enum.txt index 11df371b001..d5f52ca72b5 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enum.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enum.txt @@ -3,6 +3,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /X.Y containingEnumClassIdIfNonLocal: X contextReceivers: [] + enumEntryInitializer: null isExtension: false name: Y origin: SOURCE @@ -21,6 +22,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /X.Z containingEnumClassIdIfNonLocal: X contextReceivers: [] + enumEntryInitializer: null isExtension: false name: Z origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.descriptors.txt index 9e130895956..d293a58e8df 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.descriptors.txt @@ -39,6 +39,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.FirstEntry) isExtension: false name: FirstEntry origin: SOURCE @@ -57,6 +58,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: null isExtension: false name: SecondEntry origin: SOURCE @@ -170,6 +172,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.ThirdEntry) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.txt index 58a407080ef..1c2c04298e2 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryFunctions.txt @@ -39,6 +39,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: FirstEntry origin: SOURCE @@ -57,6 +58,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: null isExtension: false name: SecondEntry origin: SOURCE @@ -170,6 +172,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.descriptors.txt index 6e1063e1cd0..71c38cfc0eb 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.descriptors.txt @@ -75,6 +75,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.FirstEntry) isExtension: false name: FirstEntry origin: SOURCE @@ -214,6 +215,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.SecondEntry) isExtension: false name: SecondEntry origin: SOURCE @@ -327,6 +329,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.ThirdEntry) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt index 9b1fcd7d0f0..3bea5a4bef5 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryOverride.txt @@ -75,6 +75,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: FirstEntry origin: SOURCE @@ -210,6 +211,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: SecondEntry origin: SOURCE @@ -323,6 +325,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.descriptors.txt index f48eaacae52..8b8d6916eb4 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.descriptors.txt @@ -88,6 +88,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.FirstEntry) isExtension: false name: FirstEntry origin: SOURCE @@ -106,6 +107,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: null isExtension: false name: SecondEntry origin: SOURCE @@ -312,6 +314,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/MyEnumClass.ThirdEntry) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.txt index f2638820fd9..5fc9f6dff39 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumEntryProperties.txt @@ -88,6 +88,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.FirstEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: FirstEntry origin: SOURCE @@ -106,6 +107,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.SecondEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: null isExtension: false name: SecondEntry origin: SOURCE @@ -308,6 +310,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /MyEnumClass.ThirdEntry containingEnumClassIdIfNonLocal: MyEnumClass contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: ThirdEntry origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.descriptors.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.descriptors.txt index 236b7676051..5b229b494d6 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.descriptors.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.descriptors.txt @@ -217,6 +217,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /Style.SHEET containingEnumClassIdIfNonLocal: Style contextReceivers: [] + enumEntryInitializer: KtEnumEntrySymbol(/Style.SHEET) isExtension: false name: SHEET origin: SOURCE diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt index 833c7959195..a37ad949cc2 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/enumValueMember.txt @@ -213,6 +213,7 @@ KtEnumEntrySymbol: callableIdIfNonLocal: /Style.SHEET containingEnumClassIdIfNonLocal: Style contextReceivers: [] + enumEntryInitializer: KtAnonymousObjectSymbol(/) isExtension: false name: SHEET origin: SOURCE diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt index 6511f6f08c5..bf119445632 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt @@ -107,7 +107,17 @@ internal class SymbolLightClassForEnumEntry( val result = mutableListOf() // Then, add instance fields: properties from parameters, and then member properties - addPropertyBackingFields(result, enumEntrySymbol) + enumEntrySymbol.enumEntryInitializer?.let { initializer -> + addPropertyBackingFields( + result, + initializer, + + // `addPropertyBackingFields` detects that property fields should be static when the given symbol with members is an + // object. Unfortunately, the enum entry's initializer is an anonymous object, yet we want the enum entry's light class + // to have non-static properties. + forceIsStaticTo = false, + ) + } result } @@ -117,11 +127,13 @@ internal class SymbolLightClassForEnumEntry( enumConstant.withEnumEntrySymbol { enumEntrySymbol -> val result = mutableListOf() - val declaredMemberScope = enumEntrySymbol.getDeclaredMemberScope() - val visibleDeclarations = declaredMemberScope.getCallableSymbols() + enumEntrySymbol.enumEntryInitializer?.let { initializer -> + val declaredMemberScope = initializer.getDeclaredMemberScope() + val visibleDeclarations = declaredMemberScope.getCallableSymbols() - createMethods(visibleDeclarations, result) - createConstructors(declaredMemberScope.getConstructors(), result) + createMethods(visibleDeclarations, result) + createConstructors(declaredMemberScope.getConstructors(), result) + } result } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt index 1c334965cff..e094419e2c1 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt @@ -619,6 +619,7 @@ context(KtAnalysisSession) internal fun SymbolLightClassBase.addPropertyBackingFields( result: MutableList, symbolWithMembers: KtSymbolWithMembers, + forceIsStaticTo: Boolean? = null, ) { val propertySymbols = symbolWithMembers.getDeclaredMemberScope().getCallableSymbols() .filterIsInstance() @@ -633,7 +634,7 @@ internal fun SymbolLightClassBase.addPropertyBackingFields( val nameGenerator = SymbolLightField.FieldNameGenerator() - val isStatic = symbolWithMembers is KtClassOrObjectSymbol && symbolWithMembers.classKind.isObject + val isStatic = forceIsStaticTo ?: (symbolWithMembers is KtClassOrObjectSymbol && symbolWithMembers.classKind.isObject) fun addPropertyBackingField(propertySymbol: KtPropertySymbol) { createField( declaration = propertySymbol, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt index 5ac31c248bd..741810fbde3 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt @@ -96,7 +96,8 @@ internal fun KtClassOrObjectSymbol.enumClassModality(): String? { context(KtAnalysisSession) private fun KtEnumEntrySymbol.requiresSubClass(): Boolean { - return getDeclaredMemberScope().getAllSymbols().any { it !is KtConstructorSymbol } + val initializer = enumEntryInitializer ?: return false + return initializer.getDeclaredMemberScope().getAllSymbols().any { it !is KtConstructorSymbol } } internal fun KtSymbolWithVisibility.toPsiVisibilityForMember(): String = visibility.toPsiVisibilityForMember()