FIR checker: report UNINITIALIZED_ENUM_(ENTRY|COMPANION)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
ad9b962536
commit
619360fe4d
@@ -23,7 +23,7 @@ enum class Planet(val m: Double, internal val r: Double) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
val g: Double = G * m / (r * r)
|
val g: Double = <!UNINITIALIZED_VARIABLE!>G<!> * m / (r * r)
|
||||||
|
|
||||||
abstract fun sayHello()
|
abstract fun sayHello()
|
||||||
|
|
||||||
|
|||||||
+6
@@ -30900,6 +30900,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/elvisOnUnitInLet.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/elvisOnUnitInLet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntryInitialization.kt")
|
||||||
|
public void testEnumEntryInitialization() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("exitProcess.kt")
|
@TestMetadata("exitProcess.kt")
|
||||||
public void testExitProcess() throws Exception {
|
public void testExitProcess() throws Exception {
|
||||||
|
|||||||
+7
-4
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.fir.PrivateForInline
|
|||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -529,6 +526,12 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
val UNINITIALIZED_VARIABLE by error<FirSourceElement, KtSimpleNameExpression> {
|
val UNINITIALIZED_VARIABLE by error<FirSourceElement, KtSimpleNameExpression> {
|
||||||
parameter<FirPropertySymbol>("variable")
|
parameter<FirPropertySymbol>("variable")
|
||||||
}
|
}
|
||||||
|
val UNINITIALIZED_ENUM_ENTRY by error<FirSourceElement, KtSimpleNameExpression> {
|
||||||
|
parameter<FirVariableSymbol<FirEnumEntry>>("enumEntry")
|
||||||
|
}
|
||||||
|
val UNINITIALIZED_ENUM_COMPANION by error<FirSourceElement, KtSimpleNameExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
|
||||||
|
parameter<FirRegularClassSymbol>("enumClass")
|
||||||
|
}
|
||||||
val VAL_REASSIGNMENT by error<FirSourceElement, KtExpression> {
|
val VAL_REASSIGNMENT by error<FirSourceElement, KtExpression> {
|
||||||
parameter<FirVariableSymbol<*>>("variable")
|
parameter<FirVariableSymbol<*>>("variable")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStr
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
@@ -322,6 +324,8 @@ object FirErrors {
|
|||||||
|
|
||||||
// Control flow diagnostics
|
// Control flow diagnostics
|
||||||
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, KtSimpleNameExpression, FirPropertySymbol>()
|
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, KtSimpleNameExpression, FirPropertySymbol>()
|
||||||
|
val UNINITIALIZED_ENUM_ENTRY by error1<FirSourceElement, KtSimpleNameExpression, FirVariableSymbol<FirEnumEntry>>()
|
||||||
|
val UNINITIALIZED_ENUM_COMPANION by error1<FirSourceElement, KtSimpleNameExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
val VAL_REASSIGNMENT by error1<FirSourceElement, KtExpression, FirVariableSymbol<*>>()
|
val VAL_REASSIGNMENT by error1<FirSourceElement, KtExpression, FirVariableSymbol<*>>()
|
||||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by warning1<FirSourceElement, KtExpression, FirPropertySymbol>()
|
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by warning1<FirSourceElement, KtExpression, FirPropertySymbol>()
|
||||||
val VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR by error1<FirSourceElement, KtExpression, FirPropertySymbol>()
|
val VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR by error1<FirSourceElement, KtExpression, FirPropertySymbol>()
|
||||||
|
|||||||
@@ -21,11 +21,14 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
@@ -158,6 +161,16 @@ inline fun <reified T : Any> FirQualifiedAccessExpression.getDeclaration(): T? {
|
|||||||
fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeDeclaration<*>? =
|
fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeDeclaration<*>? =
|
||||||
this.safeAs<FirCallableMemberDeclaration<*>>()?.containingClass()?.toSymbol(context.session)?.fir
|
this.safeAs<FirCallableMemberDeclaration<*>>()?.containingClass()?.toSymbol(context.session)?.fir
|
||||||
|
|
||||||
|
fun FirClassLikeSymbol<*>.outerClass(context: CheckerContext): FirClassLikeSymbol<*>? {
|
||||||
|
if (this !is FirClassSymbol<*>) return null
|
||||||
|
val outerClassId = classId.outerClassId ?: return null
|
||||||
|
return context.session.symbolProvider.getClassLikeSymbolByFqName(outerClassId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirClass<*>.outerClass(context: CheckerContext): FirClass<*>? {
|
||||||
|
return symbol.outerClass(context)?.fir as? FirClass<*>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the FirClassLikeDeclaration that the
|
* Returns the FirClassLikeDeclaration that the
|
||||||
* sequence of FirTypeAlias'es points to starting
|
* sequence of FirTypeAlias'es points to starting
|
||||||
|
|||||||
+8
@@ -14,8 +14,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassAttr
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
@@ -175,6 +177,12 @@ internal fun FirRegularClass.isInlineOrValueClass(): Boolean {
|
|||||||
return isInline || hasModifier(KtTokens.VALUE_KEYWORD)
|
return isInline || hasModifier(KtTokens.VALUE_KEYWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val FirDeclaration.isEnumEntryInitializer: Boolean
|
||||||
|
get() {
|
||||||
|
if (this !is FirConstructor || !this.isPrimary) return false
|
||||||
|
return (containingClassAttr as? ConeClassLookupTagWithFixedSymbol)?.symbol?.fir?.classKind == ClassKind.ENUM_ENTRY
|
||||||
|
}
|
||||||
|
|
||||||
internal val FirMemberDeclaration.isLocalMember: Boolean
|
internal val FirMemberDeclaration.isLocalMember: Boolean
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is FirProperty -> this.isLocal
|
is FirProperty -> this.isLocal
|
||||||
|
|||||||
+227
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||||
|
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.getContainingClass
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.outerClass
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
|
|
||||||
|
object FirUninitializedEnumChecker : FirQualifiedAccessChecker() {
|
||||||
|
// Initialization order: member property initializers, enum entries, companion object (including members in it).
|
||||||
|
//
|
||||||
|
// When JVM loads a class, the corresponding class initializer, a.k.a. <clinit>, is executed first.
|
||||||
|
// Kotlin (and Java as well) converts enum entries as static final field, which is initialized in that <clinit>:
|
||||||
|
// enum class E(...) {
|
||||||
|
// E1, E2, ...
|
||||||
|
// }
|
||||||
|
// ~>
|
||||||
|
// class E {
|
||||||
|
// final static E1, E2, ...
|
||||||
|
// static { // <clinit>
|
||||||
|
// E1 = new E(...)
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// 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:
|
||||||
|
// enum class E(...) {
|
||||||
|
// E1, E2, ...
|
||||||
|
// val m1 = E1
|
||||||
|
// }
|
||||||
|
// ~>
|
||||||
|
// class E {
|
||||||
|
// E m1 ...
|
||||||
|
// E(...) { // <init>
|
||||||
|
// m1 = E1
|
||||||
|
// }
|
||||||
|
// final static E1, E2, ...
|
||||||
|
// static { // <clinit>
|
||||||
|
// E1 = new E(...)
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// A companion object is desugared to a static final singleton, and initialized in <clinit> too. However, enum lowering goes first,
|
||||||
|
// or in other words, companion object lowering goes last. Thus, any other things initialized in <clinit>, including enum entries,
|
||||||
|
// should not have access to companion object and members in it.
|
||||||
|
//
|
||||||
|
// See related discussions:
|
||||||
|
// https://youtrack.jetbrains.com/issue/KT-6054
|
||||||
|
// https://youtrack.jetbrains.com/issue/KT-11769
|
||||||
|
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val source = expression.source ?: return
|
||||||
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
|
|
||||||
|
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
|
||||||
|
val calleeDeclaration = reference.resolvedSymbol.fir
|
||||||
|
val calleeContainingClass = calleeDeclaration.getContainingClass(context) as? FirRegularClass ?: return
|
||||||
|
// We're looking for members/entries/companion object in an enum class or members in companion object of an enum class.
|
||||||
|
val calleeIsInsideEnum = calleeContainingClass.isEnumClass
|
||||||
|
val calleeIsInsideEnumCompanion =
|
||||||
|
calleeContainingClass.isCompanion && (calleeContainingClass.outerClass(context) as? FirRegularClass)?.isEnumClass == true
|
||||||
|
if (!calleeIsInsideEnum && !calleeIsInsideEnumCompanion) return
|
||||||
|
|
||||||
|
val enumClass =
|
||||||
|
if (calleeIsInsideEnum) calleeContainingClass
|
||||||
|
else calleeContainingClass.outerClass(context) as? FirRegularClass ?: return
|
||||||
|
|
||||||
|
// An accessed context within the enum class of interest. We should look up until either enum members or enum entries are found,
|
||||||
|
// not just last containing declaration. For example,
|
||||||
|
// enum class Fruit(...) {
|
||||||
|
// APPLE(...);
|
||||||
|
// companion object {
|
||||||
|
// val common = ...
|
||||||
|
// }
|
||||||
|
// val score = ... <!>common<!>
|
||||||
|
// val score2 = { ... <!>common<!> }()
|
||||||
|
// }
|
||||||
|
// 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 accessedContext = context.containingDeclarations.lastOrNull {
|
||||||
|
// To not raise an error for an access from another enum class, e.g.,
|
||||||
|
// enum class EnumCompanion4(...) {
|
||||||
|
// INSTANCE(EnumCompanion2.foo())
|
||||||
|
// }
|
||||||
|
// find an accessed context within the same enum class.
|
||||||
|
(it as? FirSymbolOwner<*>)?.getContainingClass(context) == enumClass
|
||||||
|
} ?: return
|
||||||
|
|
||||||
|
val enumMemberProperties = enumClass.declarations.filterIsInstance<FirProperty>()
|
||||||
|
val enumEntries = enumClass.declarations.filterIsInstance<FirEnumEntry>()
|
||||||
|
|
||||||
|
// When checking enum member properties, accesses to enum entries in lazy delegation is legitimate, e.g.,
|
||||||
|
// enum JvmTarget(...) {
|
||||||
|
// JVM_1_6, ...
|
||||||
|
// val bytecodeVersion: ... by lazy {
|
||||||
|
// when (this) {
|
||||||
|
// JVM_1_6 -> ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (accessedContext in enumMemberProperties) {
|
||||||
|
val lazyDelegation = (accessedContext as FirProperty).lazyDelegation
|
||||||
|
if (lazyDelegation != null && lazyDelegation == context.containingDeclarations.lastOrNull()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When checking enum entries, only entry initializer matters. For example,
|
||||||
|
// enum class EnumCompanion(...) {
|
||||||
|
// ANOTHER {
|
||||||
|
// override fun bar() = foo() // At this point, companion object is initialized
|
||||||
|
// }
|
||||||
|
// abstract bar(): ...
|
||||||
|
// companion object {
|
||||||
|
// fun foo() = ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (accessedContext in enumEntries && context.containingDeclarations.lastOrNull()?.isEnumEntryInitializer != true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members inside the companion object of an enum class
|
||||||
|
if (calleeContainingClass == enumClass.companionObject) {
|
||||||
|
// Uninitialized from the point of view of members or enum entries of that enum class
|
||||||
|
if (accessedContext in enumMemberProperties || accessedContext in enumEntries) {
|
||||||
|
if (calleeDeclaration is FirProperty) {
|
||||||
|
// From KT-11769
|
||||||
|
// enum class Fruit(...) {
|
||||||
|
// APPLE(...);
|
||||||
|
// companion object {
|
||||||
|
// val common = ...
|
||||||
|
// }
|
||||||
|
// val score = ... <!>common<!>
|
||||||
|
// }
|
||||||
|
reporter.reportOn(source, FirErrors.UNINITIALIZED_VARIABLE, calleeDeclaration.symbol, context)
|
||||||
|
} else {
|
||||||
|
// enum class EnumCompanion2(...) {
|
||||||
|
// INSTANCE(<!>foo<!>())
|
||||||
|
// companion object {
|
||||||
|
// fun foo() = ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// <!>Companion<!>.foo() v.s. <!>foo<!>()
|
||||||
|
if ((expression.explicitReceiver as? FirResolvedQualifier)?.symbol?.fir == enumClass.companionObject) {
|
||||||
|
reporter.reportOn(
|
||||||
|
expression.explicitReceiver!!.source,
|
||||||
|
FirErrors.UNINITIALIZED_ENUM_COMPANION,
|
||||||
|
enumClass.symbol,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(
|
||||||
|
expression.calleeReference.source,
|
||||||
|
FirErrors.UNINITIALIZED_ENUM_COMPANION,
|
||||||
|
enumClass.symbol,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The enum entries of an enum class
|
||||||
|
if (calleeDeclaration in enumEntries) {
|
||||||
|
val calleeEnumEntry = calleeDeclaration as FirEnumEntry
|
||||||
|
// 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.symbol, context)
|
||||||
|
}
|
||||||
|
// enum class A(...) {
|
||||||
|
// A1(<!>A2<!>),
|
||||||
|
// A2(...),
|
||||||
|
// A3(<!>A3<!>)
|
||||||
|
// }
|
||||||
|
if (accessedContext in enumEntries) {
|
||||||
|
// 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: FirEnumEntry? = null
|
||||||
|
enumEntries.forEach {
|
||||||
|
if (precedingEntry != null) return@forEach
|
||||||
|
if (it == calleeEnumEntry || it == accessedContext) {
|
||||||
|
precedingEntry = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (precedingEntry == accessedContext) {
|
||||||
|
reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry.symbol, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val FirProperty.lazyDelegation: FirAnonymousFunction?
|
||||||
|
get() {
|
||||||
|
if (delegate == null || delegate !is FirFunctionCall) return null
|
||||||
|
val delegateCall = delegate as FirFunctionCall
|
||||||
|
val callee =
|
||||||
|
(delegateCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirSimpleFunction ?: return null
|
||||||
|
if (callee.symbol.callableId.asSingleFqName().asString() != "kotlin.lazy") return null
|
||||||
|
val lazyCallArgument = delegateCall.argumentList.arguments.singleOrNull() as? FirLambdaArgumentExpression ?: return null
|
||||||
|
return lazyCallArgument.expression as? FirAnonymousFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -220,6 +220,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
||||||
@@ -722,6 +724,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
|
|
||||||
// Control flow diagnostics
|
// Control flow diagnostics
|
||||||
map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", VARIABLE_NAME)
|
map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", VARIABLE_NAME)
|
||||||
|
map.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", VARIABLE_NAME)
|
||||||
|
map.put(UNINITIALIZED_ENUM_COMPANION, "Companion object of enum class ''{0}'' is uninitialized here", SYMBOL)
|
||||||
map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME)
|
map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME)
|
||||||
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Reassignment of read-only property via backing field is deprecated", VARIABLE_NAME)
|
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD, "Reassignment of read-only property via backing field is deprecated", VARIABLE_NAME)
|
||||||
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, "Reassignment of read-only property via backing field", VARIABLE_NAME)
|
map.put(VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR, "Reassignment of read-only property via backing field", VARIABLE_NAME)
|
||||||
|
|||||||
+1
@@ -27,6 +27,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirTypeArgumentsNotAllowedExpressionChecker,
|
FirTypeArgumentsNotAllowedExpressionChecker,
|
||||||
FirTypeParameterInQualifiedAccessChecker,
|
FirTypeParameterInQualifiedAccessChecker,
|
||||||
FirSealedClassConstructorCallChecker,
|
FirSealedClassConstructorCallChecker,
|
||||||
|
FirUninitializedEnumChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf(
|
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf(
|
||||||
|
|||||||
Vendored
+31
-5
@@ -9,7 +9,7 @@ enum class B(val x: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class C(val x: Int) {
|
enum class C(val x: Int) {
|
||||||
C1(SUM),
|
C1(<!UNINITIALIZED_VARIABLE!>SUM<!>),
|
||||||
C2(1);
|
C2(1);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -26,13 +26,14 @@ enum class Fruit(personal: Int) {
|
|||||||
val common = 20
|
val common = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
val score = personal + common
|
val score = personal + <!UNINITIALIZED_VARIABLE!>common<!>
|
||||||
|
val score2 = { personal + <!UNINITIALIZED_VARIABLE!>common<!> }()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Another example from KT-11769
|
// Another example from KT-11769
|
||||||
enum class EnumCompanion1(val x: Int) {
|
enum class EnumCompanion1(val x: Int) {
|
||||||
INSTANCE(Companion.foo()),
|
INSTANCE(<!UNINITIALIZED_ENUM_COMPANION!>Companion<!>.foo()),
|
||||||
ANOTHER(foo());
|
ANOTHER(<!UNINITIALIZED_ENUM_COMPANION!>foo<!>());
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun foo() = 42
|
fun foo() = 42
|
||||||
@@ -40,7 +41,7 @@ enum class EnumCompanion1(val x: Int) {
|
|||||||
}
|
}
|
||||||
// Also should be reported for implicit receiver
|
// Also should be reported for implicit receiver
|
||||||
enum class EnumCompanion2(val x: Int) {
|
enum class EnumCompanion2(val x: Int) {
|
||||||
INSTANCE(foo());
|
INSTANCE(<!UNINITIALIZED_ENUM_COMPANION!>foo<!>());
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun foo() = 42
|
fun foo() = 42
|
||||||
@@ -53,3 +54,28 @@ enum class EnumCompanion3(val x: Int) {
|
|||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ExtractableCodeDescriptor {
|
||||||
|
fun isInterface(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ExtractionTarget(val targetName: String) {
|
||||||
|
FUNCTION("function") {
|
||||||
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor) = true
|
||||||
|
},
|
||||||
|
|
||||||
|
LAZY_PROPERTY("lazy property") {
|
||||||
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
|
// Should not report UNINITIALIZED_ENUM_COMPANION
|
||||||
|
return checkNotTrait(descriptor)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun checkNotTrait(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
|
return !descriptor.isInterface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+26
@@ -27,6 +27,7 @@ enum class Fruit(personal: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val score = personal + <!UNINITIALIZED_VARIABLE!>common<!>
|
val score = personal + <!UNINITIALIZED_VARIABLE!>common<!>
|
||||||
|
val score2 = { personal + common }()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Another example from KT-11769
|
// Another example from KT-11769
|
||||||
@@ -53,3 +54,28 @@ enum class EnumCompanion3(val x: Int) {
|
|||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ExtractableCodeDescriptor {
|
||||||
|
fun isInterface(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ExtractionTarget(val targetName: String) {
|
||||||
|
FUNCTION("function") {
|
||||||
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor) = true
|
||||||
|
},
|
||||||
|
|
||||||
|
LAZY_PROPERTY("lazy property") {
|
||||||
|
override fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
|
// Should not report UNINITIALIZED_ENUM_COMPANION
|
||||||
|
return checkNotTrait(descriptor)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun isAvailable(descriptor: ExtractableCodeDescriptor): Boolean
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun checkNotTrait(descriptor: ExtractableCodeDescriptor): Boolean {
|
||||||
|
return !descriptor.isInterface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+39
@@ -149,6 +149,44 @@ public final enum class EnumCompanion3 : kotlin.Enum<EnumCompanion3> {
|
|||||||
public final /*synthesized*/ fun values(): kotlin.Array<EnumCompanion3>
|
public final /*synthesized*/ fun values(): kotlin.Array<EnumCompanion3>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ExtractableCodeDescriptor {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun isInterface(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final enum class ExtractionTarget : kotlin.Enum<ExtractionTarget> {
|
||||||
|
enum entry FUNCTION
|
||||||
|
|
||||||
|
enum entry LAZY_PROPERTY
|
||||||
|
|
||||||
|
private constructor ExtractionTarget(/*0*/ targetName: kotlin.String)
|
||||||
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
public final val targetName: kotlin.String
|
||||||
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: ExtractionTarget): kotlin.Int
|
||||||
|
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||||
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<ExtractionTarget!>!
|
||||||
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun isAvailable(/*0*/ descriptor: ExtractableCodeDescriptor): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
public final fun checkNotTrait(/*0*/ descriptor: ExtractableCodeDescriptor): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): ExtractionTarget
|
||||||
|
public final /*synthesized*/ fun values(): kotlin.Array<ExtractionTarget>
|
||||||
|
}
|
||||||
|
|
||||||
public final enum class Fruit : kotlin.Enum<Fruit> {
|
public final enum class Fruit : kotlin.Enum<Fruit> {
|
||||||
enum entry APPLE
|
enum entry APPLE
|
||||||
|
|
||||||
@@ -156,6 +194,7 @@ public final enum class Fruit : kotlin.Enum<Fruit> {
|
|||||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
public final val score: kotlin.Int
|
public final val score: kotlin.Int
|
||||||
|
public final val score2: kotlin.Int
|
||||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Fruit): kotlin.Int
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Fruit): kotlin.Int
|
||||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
|||||||
+6
-5
@@ -1,10 +1,11 @@
|
|||||||
enum class A(val v: A) {
|
enum class A(val v: A) {
|
||||||
A1(A2),
|
A1(<!UNINITIALIZED_ENUM_ENTRY!>A2<!>),
|
||||||
A2(A1)
|
A2(A1),
|
||||||
|
A3(<!UNINITIALIZED_ENUM_ENTRY!>A3<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class D(val x: Int) {
|
enum class D(val x: Int) {
|
||||||
D1(D2.x),
|
D1(<!UNINITIALIZED_ENUM_ENTRY!>D2<!>.x),
|
||||||
D2(D1.x)
|
D2(D1.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,8 +29,8 @@ object Object1 {
|
|||||||
enum class MyEnum {
|
enum class MyEnum {
|
||||||
A, B;
|
A, B;
|
||||||
val x = when(this) {
|
val x = when(this) {
|
||||||
A -> 1
|
<!UNINITIALIZED_ENUM_ENTRY!>A<!> -> 1
|
||||||
B -> 2
|
<!UNINITIALIZED_ENUM_ENTRY!>B<!> -> 2
|
||||||
else -> 3
|
else -> 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
enum class A(val v: A) {
|
enum class A(val v: A) {
|
||||||
A1(<!UNINITIALIZED_ENUM_ENTRY!>A2<!>),
|
A1(<!UNINITIALIZED_ENUM_ENTRY!>A2<!>),
|
||||||
A2(A1)
|
A2(A1),
|
||||||
|
A3(A3)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class D(val x: Int) {
|
enum class D(val x: Int) {
|
||||||
|
|||||||
+2
@@ -5,6 +5,8 @@ public final enum class A : kotlin.Enum<A> {
|
|||||||
|
|
||||||
enum entry A2
|
enum entry A2
|
||||||
|
|
||||||
|
enum entry A3
|
||||||
|
|
||||||
private constructor A(/*0*/ v: A)
|
private constructor A(/*0*/ v: A)
|
||||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
enum class JvmTarget(val description: String) {
|
||||||
|
JVM_1_6("1.6"),
|
||||||
|
JVM_1_8("1.8"),
|
||||||
|
JVM_9("9"),
|
||||||
|
JVM_10("10"),
|
||||||
|
JVM_11("11"),
|
||||||
|
JVM_12("12"),
|
||||||
|
JVM_13("13"),
|
||||||
|
JVM_14("14"),
|
||||||
|
JVM_15("15"),
|
||||||
|
;
|
||||||
|
|
||||||
|
// Should not report UNINITIALIZED_ENUM_ENTRY
|
||||||
|
val bytecodeVersion: String by lazy {
|
||||||
|
when (this) {
|
||||||
|
JVM_1_6 -> "Opcodes.V1_6"
|
||||||
|
JVM_1_8 -> "Opcodes.V1_8"
|
||||||
|
JVM_9 -> "Opcodes.V9"
|
||||||
|
JVM_10 -> "Opcodes.V10"
|
||||||
|
JVM_11 -> "Opcodes.V11"
|
||||||
|
JVM_12 -> "Opcodes.V12"
|
||||||
|
JVM_13 -> "Opcodes.V12 + 1"
|
||||||
|
JVM_14 -> "Opcodes.V12 + 2"
|
||||||
|
JVM_15 -> "Opcodes.V12 + 3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final enum class JvmTarget : kotlin.Enum<JvmTarget> {
|
||||||
|
enum entry JVM_1_6
|
||||||
|
|
||||||
|
enum entry JVM_1_8
|
||||||
|
|
||||||
|
enum entry JVM_9
|
||||||
|
|
||||||
|
enum entry JVM_10
|
||||||
|
|
||||||
|
enum entry JVM_11
|
||||||
|
|
||||||
|
enum entry JVM_12
|
||||||
|
|
||||||
|
enum entry JVM_13
|
||||||
|
|
||||||
|
enum entry JVM_14
|
||||||
|
|
||||||
|
enum entry JVM_15
|
||||||
|
|
||||||
|
private constructor JvmTarget(/*0*/ description: kotlin.String)
|
||||||
|
public final val bytecodeVersion: kotlin.String
|
||||||
|
public final val description: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: JvmTarget): kotlin.Int
|
||||||
|
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||||
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<JvmTarget!>!
|
||||||
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): JvmTarget
|
||||||
|
public final /*synthesized*/ fun values(): kotlin.Array<JvmTarget>
|
||||||
|
}
|
||||||
Generated
+6
@@ -30996,6 +30996,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/elvisOnUnitInLet.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/elvisOnUnitInLet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntryInitialization.kt")
|
||||||
|
public void testEnumEntryInitialization() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("exitProcess.kt")
|
@TestMetadata("exitProcess.kt")
|
||||||
public void testExitProcess() throws Exception {
|
public void testExitProcess() throws Exception {
|
||||||
|
|||||||
+7
-6
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DiagnosticParamet
|
|||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
@@ -30,7 +27,6 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.full.createType
|
import kotlin.reflect.full.createType
|
||||||
@@ -147,6 +143,11 @@ private object FirToKtConversionCreator {
|
|||||||
KtClassLikeSymbol::class.createType(),
|
KtClassLikeSymbol::class.createType(),
|
||||||
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirClass")
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirClass")
|
||||||
),
|
),
|
||||||
|
FirRegularClassSymbol::class to HLFunctionCallConversion(
|
||||||
|
"firSymbolBuilder.classifierBuilder.buildClassLikeSymbol({0}.fir)",
|
||||||
|
KtClassLikeSymbol::class.createType(),
|
||||||
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirRegularClass")
|
||||||
|
),
|
||||||
FirMemberDeclaration::class to HLFunctionCallConversion(
|
FirMemberDeclaration::class to HLFunctionCallConversion(
|
||||||
"firSymbolBuilder.buildSymbol({0} as FirDeclaration)",
|
"firSymbolBuilder.buildSymbol({0} as FirDeclaration)",
|
||||||
KtSymbol::class.createType(),
|
KtSymbol::class.createType(),
|
||||||
@@ -171,7 +172,7 @@ private object FirToKtConversionCreator {
|
|||||||
KtType::class.createType()
|
KtType::class.createType()
|
||||||
),
|
),
|
||||||
FirPropertySymbol::class to HLFunctionCallConversion(
|
FirPropertySymbol::class to HLFunctionCallConversion(
|
||||||
"firSymbolBuilder.variableLikeBuilder.buildVariableSymbol({0}.fir as FirProperty)",
|
"firSymbolBuilder.variableLikeBuilder.buildVariableSymbol({0}.fir)",
|
||||||
KtVariableSymbol::class.createType(),
|
KtVariableSymbol::class.createType(),
|
||||||
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirProperty")
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirProperty")
|
||||||
),
|
),
|
||||||
|
|||||||
+18
-3
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
@@ -1471,7 +1472,21 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
}
|
}
|
||||||
add(FirErrors.UNINITIALIZED_VARIABLE) { firDiagnostic ->
|
add(FirErrors.UNINITIALIZED_VARIABLE) { firDiagnostic ->
|
||||||
UninitializedVariableImpl(
|
UninitializedVariableImpl(
|
||||||
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir as FirProperty),
|
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.UNINITIALIZED_ENUM_ENTRY) { firDiagnostic ->
|
||||||
|
UninitializedEnumEntryImpl(
|
||||||
|
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a.fir),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.UNINITIALIZED_ENUM_COMPANION) { firDiagnostic ->
|
||||||
|
UninitializedEnumCompanionImpl(
|
||||||
|
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a.fir),
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
@@ -1485,14 +1500,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
}
|
}
|
||||||
add(FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD) { firDiagnostic ->
|
add(FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD) { firDiagnostic ->
|
||||||
ValReassignmentViaBackingFieldImpl(
|
ValReassignmentViaBackingFieldImpl(
|
||||||
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir as FirProperty),
|
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir),
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
add(FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR) { firDiagnostic ->
|
add(FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD_ERROR) { firDiagnostic ->
|
||||||
ValReassignmentViaBackingFieldErrorImpl(
|
ValReassignmentViaBackingFieldErrorImpl(
|
||||||
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir as FirProperty),
|
firSymbolBuilder.variableLikeBuilder.buildVariableSymbol(firDiagnostic.a.fir),
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
|
|||||||
+10
@@ -1044,6 +1044,16 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val variable: KtVariableSymbol
|
abstract val variable: KtVariableSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class UninitializedEnumEntry : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||||
|
override val diagnosticClass get() = UninitializedEnumEntry::class
|
||||||
|
abstract val enumEntry: KtVariableLikeSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UninitializedEnumCompanion : KtFirDiagnostic<KtSimpleNameExpression>() {
|
||||||
|
override val diagnosticClass get() = UninitializedEnumCompanion::class
|
||||||
|
abstract val enumClass: KtClassLikeSymbol
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ValReassignment : KtFirDiagnostic<KtExpression>() {
|
abstract class ValReassignment : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = ValReassignment::class
|
override val diagnosticClass get() = ValReassignment::class
|
||||||
abstract val variable: KtVariableLikeSymbol
|
abstract val variable: KtVariableLikeSymbol
|
||||||
|
|||||||
+16
@@ -1687,6 +1687,22 @@ internal class UninitializedVariableImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class UninitializedEnumEntryImpl(
|
||||||
|
override val enumEntry: KtVariableLikeSymbol,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UninitializedEnumEntry(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UninitializedEnumCompanionImpl(
|
||||||
|
override val enumClass: KtClassLikeSymbol,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UninitializedEnumCompanion(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ValReassignmentImpl(
|
internal class ValReassignmentImpl(
|
||||||
override val variable: KtVariableLikeSymbol,
|
override val variable: KtVariableLikeSymbol,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
Reference in New Issue
Block a user