diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt index 38338be4aa7..4d0018934a6 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt @@ -10,6 +10,8 @@ import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance import org.jetbrains.kotlin.analysis.api.KtTypeProjection +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirFunctionLikeSubstitutorBasedSignature +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirVariableLikeSubstitutorBasedSignature import org.jetbrains.kotlin.analysis.api.fir.symbols.* import org.jetbrains.kotlin.analysis.api.fir.types.* import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken @@ -21,16 +23,13 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries -import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry -import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry -import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolEntry import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider -import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.impl.FirFieldImpl import org.jetbrains.kotlin.fir.declarations.FirOuterClassTypeParameterRef +import org.jetbrains.kotlin.fir.declarations.impl.FirFieldImpl import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferTypeParameterType import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.java.declarations.FirJavaField @@ -48,6 +47,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectOrStaticData import org.jetbrains.kotlin.fir.scopes.impl.toConeType import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag @@ -56,15 +56,16 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry +import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry +import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolEntry import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract -import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirFunctionLikeSubstitutorBasedSignature -import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirVariableLikeSubstitutorBasedSignature -import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectOrStaticData /** * Maps FirElement to KtSymbol & ConeType to KtType, thread safe @@ -160,7 +161,12 @@ internal class KtSymbolByFirBuilder constructor( } fun buildAnonymousObjectSymbol(symbol: FirAnonymousObjectSymbol): KtAnonymousObjectSymbol { - return symbolsCache.cache(symbol) { KtFirAnonymousObjectSymbol(symbol, analysisSession) } + return symbolsCache.cache(symbol) { + when (symbol.classKind) { + ClassKind.ENUM_ENTRY -> KtFirEnumEntryInitializerSymbol(symbol, analysisSession) + else -> KtFirAnonymousObjectSymbol(symbol, analysisSession) + } + } } fun buildTypeAliasSymbol(symbol: FirTypeAliasSymbol): KtFirTypeAliasSymbol { 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 2a0b77161a8..fbb6bea08e7 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 @@ -6,27 +6,23 @@ package org.jetbrains.kotlin.analysis.api.fir.symbols import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForDeclaration import org.jetbrains.kotlin.analysis.api.fir.getAllowedPsi -import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.KtFirEnumEntryInitializerSymbolPointer -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.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 import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol -internal class KtFirAnonymousObjectSymbol( +internal open class KtFirAnonymousObjectSymbol( override val firSymbol: FirAnonymousObjectSymbol, override val analysisSession: KtFirAnalysisSession, -) : KtAnonymousObjectSymbol(), KtEnumEntryInitializerSymbol, KtFirSymbol { +) : KtAnonymousObjectSymbol(), KtFirSymbol { override val psi: PsiElement? = withValidityAssertion { firSymbol.fir.getAllowedPsi() } override val annotationsList by cached { @@ -38,9 +34,6 @@ internal class KtFirAnonymousObjectSymbol( context(KtAnalysisSession) override fun createPointer(): KtSymbolPointer = withValidityAssertion { KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } - if (firSymbol.source?.kind == KtFakeSourceElementKind.EnumInitializer) { - return KtFirEnumEntryInitializerSymbolPointer(requireOwnerPointer()) - } throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException(this::class) } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntryInitializerSymbol.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntryInitializerSymbol.kt new file mode 100644 index 00000000000..246766bf47c --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirEnumEntryInitializerSymbol.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.symbols + +import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.KtFirEnumEntryInitializerSymbolPointer +import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.requireOwnerPointer +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntryInitializerSymbol +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol + +internal class KtFirEnumEntryInitializerSymbol( + firSymbol: FirAnonymousObjectSymbol, + analysisSession: KtFirAnalysisSession, +) : KtFirAnonymousObjectSymbol(firSymbol, analysisSession), KtEnumEntryInitializerSymbol { + init { + check(firSymbol.source?.kind == KtFakeSourceElementKind.EnumInitializer) { + "Expected the `firSymbol` of ${KtFirEnumEntryInitializerSymbol::class.simpleName} to have an enum initializer fake source kind." + } + } + + /** + * [KtFirEnumEntryInitializerSymbol] is the required return type instead of [KtEnumEntryInitializerSymbol] to fulfill return type + * subtyping requirements, as [KtEnumEntryInitializerSymbol] is not a subtype of + * [org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousObjectSymbol]. (It cannot be a subtype in the general Analysis API because enum + * entry initializers are classes in FE10.) + */ + context(KtAnalysisSession) + override fun createPointer(): KtSymbolPointer = withValidityAssertion { + KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } + + KtFirEnumEntryInitializerSymbolPointer(requireOwnerPointer()) + } +} 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 998b3a5f6a3..28a382e24dc 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,7 +15,6 @@ 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 @@ -45,7 +44,7 @@ internal class KtFirEnumEntrySymbol( override val callableIdIfNonLocal: CallableId? get() = withValidityAssertion { firSymbol.getCallableIdIfNonLocal() } - override val enumEntryInitializer: KtEnumEntryInitializerSymbol? by cached { + override val enumEntryInitializer: KtFirEnumEntryInitializerSymbol? by cached { if (firSymbol.fir.initializer == null) { return@cached null } @@ -56,7 +55,10 @@ internal class KtFirEnumEntrySymbol( check(initializerExpression is FirAnonymousObjectExpression) { "Unexpected enum entry initializer: ${initializerExpression?.javaClass}" } - KtFirAnonymousObjectSymbol(initializerExpression.anonymousObject.symbol, analysisSession) + + val classifierBuilder = analysisSession.firSymbolBuilder.classifierBuilder + classifierBuilder.buildAnonymousObjectSymbol(initializerExpression.anonymousObject.symbol) as? KtFirEnumEntryInitializerSymbol + ?: error("The anonymous object symbol for an enum entry initializer should be a ${KtFirEnumEntryInitializerSymbol::class.simpleName}") } context(KtAnalysisSession) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/pointers/KtFirEnumEntryInitializerSymbolPointer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/pointers/KtFirEnumEntryInitializerSymbolPointer.kt index 64732ebfbfe..fca4682f39b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/pointers/KtFirEnumEntryInitializerSymbolPointer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/pointers/KtFirEnumEntryInitializerSymbolPointer.kt @@ -7,25 +7,21 @@ package org.jetbrains.kotlin.analysis.api.fir.symbols.pointers import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession -import org.jetbrains.kotlin.analysis.api.fir.utils.firSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousObjectSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol +import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirEnumEntryInitializerSymbol +import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirEnumEntrySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer -import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression internal class KtFirEnumEntryInitializerSymbolPointer( - private val ownerPointer: KtSymbolPointer, -) : KtSymbolPointer() { + private val ownerPointer: KtSymbolPointer, +) : KtSymbolPointer() { @Deprecated("Consider using org.jetbrains.kotlin.analysis.api.KtAnalysisSession.restoreSymbol") - override fun restoreSymbol(analysisSession: KtAnalysisSession): KtAnonymousObjectSymbol? { + override fun restoreSymbol(analysisSession: KtAnalysisSession): KtFirEnumEntryInitializerSymbol? { require(analysisSession is KtFirAnalysisSession) val owner = with(analysisSession) { ownerPointer.restoreSymbol() } - - val initializer = owner?.firSymbol?.fir?.initializer as? FirAnonymousObjectExpression ?: return null - return analysisSession.firSymbolBuilder.classifierBuilder.buildAnonymousObjectSymbol(initializer.anonymousObject.symbol) + return owner?.enumEntryInitializer } override fun pointsToTheSameSymbolAs(other: KtSymbolPointer): Boolean = this === other || diff --git a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.pretty.txt b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.pretty.txt index eb6d23f19aa..505510175b1 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.pretty.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.pretty.txt @@ -1,7 +1,7 @@ element: e implicit receivers: type: `` - owner symbol: KtFirAnonymousObjectSymbol + owner symbol: KtFirEnumEntryInitializerSymbol type: kotlin.Enum.Companion owner symbol: KtFirNamedClassOrObjectSymbol diff --git a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt index 91066dcd5dd..02059af8818 100644 --- a/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt +++ b/analysis/analysis-api/testData/components/scopeProvider/scopeContextForPosition/enumEntry.txt @@ -4,7 +4,7 @@ implicit receivers: annotationsList: [] ownTypeArguments: [] type: - owner symbol: KtFirAnonymousObjectSymbol + owner symbol: KtFirEnumEntryInitializerSymbol type: KtUsualClassType: annotationsList: []