[FIR] Fix reporting of UNINITIALIZED_ENUM_ENTRY in init blocks
^KT-41126 Fixed
This commit is contained in:
committed by
Space Team
parent
c596c1ad73
commit
a9248569a6
+1
-1
@@ -2313,7 +2313,7 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val parameter: KtSymbol
|
||||
}
|
||||
|
||||
abstract class UninitializedEnumEntry : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||
abstract class UninitializedEnumEntry : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = UninitializedEnumEntry::class
|
||||
abstract val enumEntry: KtSymbol
|
||||
}
|
||||
|
||||
+1
-1
@@ -2793,7 +2793,7 @@ internal class UninitializedEnumEntryImpl(
|
||||
override val enumEntry: KtSymbol,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.UninitializedEnumEntry(), KtAbstractFirDiagnostic<KtSimpleNameExpression>
|
||||
) : KtFirDiagnostic.UninitializedEnumEntry(), KtAbstractFirDiagnostic<KtExpression>
|
||||
|
||||
internal class UninitializedEnumCompanionImpl(
|
||||
override val enumClass: KtClassLikeSymbol,
|
||||
|
||||
+1
-1
@@ -1133,7 +1133,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val UNINITIALIZED_PARAMETER by error<KtSimpleNameExpression> {
|
||||
parameter<FirValueParameterSymbol>("parameter")
|
||||
}
|
||||
val UNINITIALIZED_ENUM_ENTRY by error<KtSimpleNameExpression> {
|
||||
val UNINITIALIZED_ENUM_ENTRY by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
parameter<FirEnumEntrySymbol>("enumEntry")
|
||||
}
|
||||
val UNINITIALIZED_ENUM_COMPANION by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||
|
||||
+1
-1
@@ -607,7 +607,7 @@ object FirErrors {
|
||||
// Control flow diagnostics
|
||||
val UNINITIALIZED_VARIABLE by error1<KtExpression, FirPropertySymbol>()
|
||||
val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirValueParameterSymbol>()
|
||||
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirEnumEntrySymbol>()
|
||||
val UNINITIALIZED_ENUM_ENTRY by error1<KtExpression, FirEnumEntrySymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val UNINITIALIZED_ENUM_COMPANION by error1<KtExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField, SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||
|
||||
@@ -131,6 +131,7 @@ fun FirTypeRef.toRegularClassSymbol(session: FirSession): FirRegularClassSymbol?
|
||||
fun FirBasedSymbol<*>.getContainingClassSymbol(session: FirSession): FirClassLikeSymbol<*>? = when (this) {
|
||||
is FirCallableSymbol<*> -> containingClassLookupTag()?.toSymbol(session)
|
||||
is FirClassLikeSymbol<*> -> getContainingClassLookupTag()?.toSymbol(session)
|
||||
is FirAnonymousInitializerSymbol -> dispatchReceiverType?.toSymbol(session) as? FirClassLikeSymbol<*>
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
-6
@@ -83,12 +83,6 @@ internal fun FirMemberDeclaration.isEffectivelyExternal(
|
||||
|
||||
internal val FirClass.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS
|
||||
|
||||
internal val FirDeclaration.isEnumEntryInitializer: Boolean
|
||||
get() {
|
||||
if (this !is FirConstructor || !this.isPrimary) return false
|
||||
return (containingClassForStaticMemberAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.classKind == ClassKind.ENUM_ENTRY
|
||||
}
|
||||
|
||||
// contract: returns(true) implies (this is FirMemberDeclaration<*>)
|
||||
val FirDeclaration.isLocalMember: Boolean
|
||||
get() = symbol.isLocalMember
|
||||
|
||||
+101
-37
@@ -6,25 +6,27 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isEnumEntryInitializer
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.outerClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.flatAssociateBy
|
||||
|
||||
object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
// Initialization order: member property initializers, enum entries, companion object (including members in it).
|
||||
@@ -44,8 +46,8 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
// }
|
||||
//
|
||||
// Note that, when initializing enum entries, now we call the enum class's constructor, a.k.a. <init>, to initialize non-final
|
||||
// instance members. Therefore, if there is a member property in the enum class, and if that member has an access to enum entries,
|
||||
// that is an illegal access since enum entries are not yet initialized:
|
||||
// instance members. Therefore, if there is a member property in the enum class, and if that member has access to enum entries,
|
||||
// that is illegal access since enum entries are not yet initialized:
|
||||
// enum class E(...) {
|
||||
// E1, E2, ...
|
||||
// val m1 = E1
|
||||
@@ -99,19 +101,28 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
// companion object is not initialized for both member properties. The former has the property itself as the last containing
|
||||
// declaration, whereas the latter has an anonymous function instead. For both cases, we're looking for member properties as an
|
||||
// accessed context.
|
||||
val isInsideCorrespondingEnum = context.containingDeclarations.any {
|
||||
it.getContainingClassSymbol(context.session) == enumClassSymbol
|
||||
}
|
||||
if (!isInsideCorrespondingEnum) return
|
||||
|
||||
val declarationSymbols = enumClassSymbol.declarationSymbols
|
||||
val enumMemberProperties = declarationSymbols.filterIsInstance<FirPropertySymbol>()
|
||||
val enumInitBlocks = declarationSymbols.filterIsInstance<FirAnonymousInitializerSymbol>()
|
||||
val enumEntries = declarationSymbols.filterIsInstance<FirEnumEntrySymbol>()
|
||||
val enumEntriesInitBlocks = enumEntries.flatAssociateBy {
|
||||
it.initializerObjectSymbol?.declarationSymbols?.filterIsInstance<FirAnonymousInitializerSymbol>().orEmpty()
|
||||
}
|
||||
|
||||
val accessedContext = context.containingDeclarations.lastOrNull {
|
||||
// To not raise an error for an access from another enum class, e.g.,
|
||||
// To not raise an error for access from another enum class, e.g.,
|
||||
// enum class EnumCompanion4(...) {
|
||||
// INSTANCE(EnumCompanion2.foo())
|
||||
// }
|
||||
// find an accessed context within the same enum class.
|
||||
it.getContainingClassSymbol(context.session) == enumClassSymbol
|
||||
it.getContainingClassSymbol(context.session) == enumClassSymbol || it.symbol in enumEntriesInitBlocks
|
||||
}?.symbol ?: return
|
||||
|
||||
val declarationSymbols = enumClassSymbol.declarationSymbols
|
||||
val enumMemberProperties = declarationSymbols.filterIsInstance<FirPropertySymbol>()
|
||||
val enumEntries = declarationSymbols.filterIsInstance<FirEnumEntrySymbol>()
|
||||
|
||||
// When checking enum member properties, accesses to enum entries in lazy delegation is legitimate, e.g.,
|
||||
// enum JvmTarget(...) {
|
||||
// JVM_1_6, ...
|
||||
@@ -120,9 +131,10 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
// JVM_1_6 -> ...
|
||||
// }
|
||||
// }
|
||||
val containingDeclarationForAccess = context.containingDeclarations.lastOrNull()
|
||||
if (accessedContext in enumMemberProperties) {
|
||||
val lazyDelegation = (accessedContext as FirPropertySymbol).lazyDelegation
|
||||
if (lazyDelegation != null && lazyDelegation == context.containingDeclarations.lastOrNull()) {
|
||||
if (lazyDelegation != null && lazyDelegation == containingDeclarationForAccess) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -137,7 +149,7 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
// fun foo() = ...
|
||||
// }
|
||||
// }
|
||||
if (accessedContext in enumEntries && context.containingDeclarations.lastOrNull()?.isEnumEntryInitializer != true) {
|
||||
if (accessedContext in enumEntries && containingDeclarationForAccess?.isEnumEntryInitializer(context.session) != true) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -163,36 +175,74 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
if (calleeSymbol in enumEntries) {
|
||||
val calleeEnumEntry = calleeSymbol as FirEnumEntrySymbol
|
||||
// Uninitialized from the point of view of members of that enum class
|
||||
if (accessedContext in enumMemberProperties) {
|
||||
// From KT-6054
|
||||
// enum class MyEnum {
|
||||
// A, B;
|
||||
// val x = when(this) {
|
||||
// <!>A<!> -> ...
|
||||
// <!>B<!> -> ...
|
||||
// }
|
||||
// }
|
||||
reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry, context)
|
||||
}
|
||||
// enum class A(...) {
|
||||
// A1(<!>A2<!>),
|
||||
// A2(...),
|
||||
// A3(<!>A3<!>)
|
||||
// }
|
||||
if (accessedContext in enumEntries) {
|
||||
|
||||
fun reportIllegalAccessInEnumEntry(correspondingEnumEntry: FirEnumEntrySymbol) {
|
||||
// Technically, this is equal to `enumEntries.indexOf(accessedContext) <= enumEntries.indexOf(calleeDeclaration)`.
|
||||
// Instead of double `indexOf`, we can iterate entries just once until either one appears.
|
||||
var precedingEntry: FirEnumEntrySymbol? = null
|
||||
enumEntries.forEach {
|
||||
if (precedingEntry != null) return@forEach
|
||||
if (it == calleeEnumEntry || it == accessedContext) {
|
||||
for (it in enumEntries) {
|
||||
if (it == calleeEnumEntry || it == correspondingEnumEntry) {
|
||||
precedingEntry = it
|
||||
break
|
||||
}
|
||||
}
|
||||
if (precedingEntry == accessedContext) {
|
||||
if (precedingEntry == correspondingEnumEntry) {
|
||||
reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry, context)
|
||||
}
|
||||
}
|
||||
|
||||
when (accessedContext) {
|
||||
in enumMemberProperties,
|
||||
in enumInitBlocks -> {
|
||||
/* From KT-6054
|
||||
* enum class MyEnum {
|
||||
* A, B;
|
||||
* val x = when(this) {
|
||||
* <!>A<!> -> ...
|
||||
* <!>B<!> -> ...
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry, context)
|
||||
}
|
||||
|
||||
in enumEntries -> {
|
||||
/*
|
||||
* enum class A(...) {
|
||||
* A1(<!>A2<!>),
|
||||
* A2(...),
|
||||
* A3(<!>A3<!>)
|
||||
* }
|
||||
*/
|
||||
reportIllegalAccessInEnumEntry(accessedContext as FirEnumEntrySymbol)
|
||||
}
|
||||
|
||||
in enumEntriesInitBlocks -> {
|
||||
/*
|
||||
* enum class MyEnum {
|
||||
* A {
|
||||
* init { A }
|
||||
* },
|
||||
* B;
|
||||
* }
|
||||
*/
|
||||
val entrySymbol = enumEntriesInitBlocks.getValue(accessedContext as FirAnonymousInitializerSymbol)
|
||||
/*
|
||||
* In init block of entry this entry already initialized, so it's safe to access it
|
||||
* enum class MyEnum {
|
||||
* A {
|
||||
* init {
|
||||
* A // safe
|
||||
* B // unsafe
|
||||
* }
|
||||
* },
|
||||
* B
|
||||
* }
|
||||
*/
|
||||
if (entrySymbol == calleeSymbol) return
|
||||
reportIllegalAccessInEnumEntry(entrySymbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,4 +258,18 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() {
|
||||
val lazyCallArgument = delegateCall.argumentList.arguments.singleOrNull() as? FirLambdaArgumentExpression ?: return null
|
||||
return (lazyCallArgument.expression as? FirAnonymousFunctionExpression)?.anonymousFunction
|
||||
}
|
||||
|
||||
private fun FirDeclaration.isEnumEntryInitializer(session: FirSession): Boolean {
|
||||
val containingClassSymbol = when (this) {
|
||||
is FirConstructor -> {
|
||||
if (!isPrimary) return false
|
||||
(containingClassForStaticMemberAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol
|
||||
}
|
||||
is FirAnonymousInitializer -> {
|
||||
dispatchReceiverType?.toSymbol(session)
|
||||
}
|
||||
else -> null
|
||||
} ?: return false
|
||||
return containingClassSymbol.classKind == ClassKind.ENUM_ENTRY
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
@@ -30,7 +30,7 @@ abstract class FirAnonymousInitializer : FirDeclaration(), FirControlFlowGraphOw
|
||||
abstract override val controlFlowGraphReference: FirControlFlowGraphReference?
|
||||
abstract val body: FirBlock?
|
||||
abstract override val symbol: FirAnonymousInitializerSymbol
|
||||
abstract val dispatchReceiverType: ConeSimpleKotlinType?
|
||||
abstract val dispatchReceiverType: ConeClassLikeType?
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitAnonymousInitializer(this, data)
|
||||
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
|
||||
/*
|
||||
@@ -40,7 +40,7 @@ class FirAnonymousInitializerBuilder : FirDeclarationBuilder, FirAnnotationConta
|
||||
override var attributes: FirDeclarationAttributes = FirDeclarationAttributes()
|
||||
var body: FirBlock? = null
|
||||
var symbol: FirAnonymousInitializerSymbol = FirAnonymousInitializerSymbol()
|
||||
var dispatchReceiverType: ConeSimpleKotlinType? = null
|
||||
var dispatchReceiverType: ConeClassLikeType? = null
|
||||
|
||||
override fun build(): FirAnonymousInitializer {
|
||||
return FirAnonymousInitializerImpl(
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.fir.MutableOrEmptyList
|
||||
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
|
||||
@@ -36,7 +36,7 @@ internal class FirAnonymousInitializerImpl(
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
override var body: FirBlock?,
|
||||
override val symbol: FirAnonymousInitializerSymbol,
|
||||
override val dispatchReceiverType: ConeSimpleKotlinType?,
|
||||
override val dispatchReceiverType: ConeClassLikeType?,
|
||||
) : FirAnonymousInitializer() {
|
||||
override val annotations: List<FirAnnotation> get() = emptyList()
|
||||
override var controlFlowGraphReference: FirControlFlowGraphReference? = null
|
||||
|
||||
+4
@@ -7,7 +7,11 @@ package org.jetbrains.kotlin.fir.symbols.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousInitializer
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||
|
||||
class FirAnonymousInitializerSymbol : FirBasedSymbol<FirAnonymousInitializer>() {
|
||||
override fun toString(): String = "${this::class.simpleName} <init>"
|
||||
|
||||
val dispatchReceiverType: ConeSimpleKotlinType?
|
||||
get() = fir.dispatchReceiverType
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.symbols.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
@@ -94,7 +95,10 @@ class FirFieldSymbol(callableId: CallableId) : FirVariableSymbol<FirField>(calla
|
||||
get() = fir.isVar
|
||||
}
|
||||
|
||||
class FirEnumEntrySymbol(callableId: CallableId) : FirVariableSymbol<FirEnumEntry>(callableId)
|
||||
class FirEnumEntrySymbol(callableId: CallableId) : FirVariableSymbol<FirEnumEntry>(callableId) {
|
||||
val initializerObjectSymbol: FirAnonymousObjectSymbol?
|
||||
get() = (fir.initializer as? FirAnonymousObjectExpression)?.anonymousObject?.symbol
|
||||
}
|
||||
|
||||
class FirValueParameterSymbol(name: Name) : FirVariableSymbol<FirValueParameter>(CallableId(name)) {
|
||||
val hasDefaultValue: Boolean
|
||||
|
||||
+1
-1
@@ -453,7 +453,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
anonymousInitializer.configure {
|
||||
+body(nullable = true, withReplace = true)
|
||||
+symbol("FirAnonymousInitializerSymbol")
|
||||
+field("dispatchReceiverType", coneSimpleKotlinTypeType, nullable = true)
|
||||
+field("dispatchReceiverType", coneClassLikeTypeType, nullable = true)
|
||||
}
|
||||
|
||||
danglingModifierList.configure {
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.generatedType
|
||||
import org.jetbrains.kotlin.fir.tree.generator.context.type
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -44,6 +45,7 @@ val annotationUseSiteTargetType = type(AnnotationUseSiteTarget::class)
|
||||
val operationKindType = type("fir.expressions", "LogicOperationKind")
|
||||
val coneKotlinTypeType = type(ConeKotlinType::class)
|
||||
val coneSimpleKotlinTypeType = type(ConeSimpleKotlinType::class)
|
||||
val coneClassLikeTypeType = type(ConeClassLikeType::class)
|
||||
|
||||
val whenRefType = generatedType("", "FirExpressionRef<FirWhenExpression>")
|
||||
val referenceToSimpleExpressionType = generatedType("", "FirExpressionRef<FirExpression>")
|
||||
|
||||
Vendored
-55
@@ -1,55 +0,0 @@
|
||||
// LANGUAGE: +ProhibitQualifiedAccessToUninitializedEnumEntry
|
||||
// ISSUE: KT-41124
|
||||
|
||||
enum class SomeEnum11(var x: Int) {
|
||||
A(1),
|
||||
B(2);
|
||||
|
||||
init {
|
||||
A.x = 10 // Error
|
||||
}
|
||||
}
|
||||
|
||||
enum class SomeEnum12(var x: Int) {
|
||||
A(1),
|
||||
B(2);
|
||||
|
||||
init {
|
||||
SomeEnum12.A.x = 10 // Error
|
||||
}
|
||||
}
|
||||
|
||||
enum class SomeEnum21(var x: Int) {
|
||||
A(1) {
|
||||
init {
|
||||
A.x = 10 // OK
|
||||
SomeEnum21.A.x = 10 // OK
|
||||
B.x = 10 // Error
|
||||
}
|
||||
},
|
||||
B(2)
|
||||
}
|
||||
|
||||
enum class SomeEnum22(var x: Int) {
|
||||
A(1) {
|
||||
init {
|
||||
A.x = 10 // OK
|
||||
SomeEnum22.A.x = 10 // OK
|
||||
SomeEnum22.B.x = 10 // Migration error
|
||||
}
|
||||
},
|
||||
B(2)
|
||||
}
|
||||
|
||||
|
||||
enum class SomeEnum3(var x: Int) {
|
||||
A(1),
|
||||
B(2) {
|
||||
init {
|
||||
A.x = 10 // OK
|
||||
SomeEnum3.A.x = 10 // OK
|
||||
B.x = 10 // OK
|
||||
SomeEnum3.B.x = 10 // OK
|
||||
}
|
||||
};
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// LANGUAGE: +ProhibitQualifiedAccessToUninitializedEnumEntry
|
||||
// ISSUE: KT-41124
|
||||
|
||||
|
||||
@@ -292,6 +292,16 @@ inline fun <T, U, K, V> List<T>.flatGroupBy(
|
||||
return result
|
||||
}
|
||||
|
||||
inline fun <T, K> List<T>.flatAssociateBy(selector: (T) -> Collection<K>): Map<K, T> {
|
||||
return buildMap {
|
||||
for (value in this@flatAssociateBy) {
|
||||
for (key in selector(value)) {
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <E> MutableList<E>.popLast(): E = removeAt(lastIndex)
|
||||
|
||||
fun <K : Enum<K>, V> enumMapOf(vararg pairs: Pair<K, V>): EnumMap<K, V> = EnumMap(mapOf(*pairs))
|
||||
|
||||
Reference in New Issue
Block a user