diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index c2ef82a7066..1cdfbf871b0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -64,6 +64,8 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirOpenMemberChecker, FirClassVarianceChecker, FirSealedSupertypeChecker, + FirMemberFunctionsChecker, + FirMemberPropertiesChecker, ) override val regularClassCheckers: Set @@ -83,8 +85,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirPrimaryConstructorSuperTypeChecker, FirTypeParametersInObjectChecker, FirFunInterfaceDeclarationChecker, - FirMemberFunctionsChecker, - FirMemberPropertiesChecker, FirNestedClassChecker, FirInlineClassDeclarationChecker, ) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt index d5ef28147c3..bdfac883321 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt @@ -25,26 +25,26 @@ import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.lexer.KtTokens -internal fun isInsideExpectClass(containingClass: FirRegularClass, context: CheckerContext): Boolean { - return isInsideSpecificClass(containingClass, context) { klass -> klass.isExpect } +internal fun isInsideExpectClass(containingClass: FirClass, context: CheckerContext): Boolean { + return isInsideSpecificClass(containingClass, context) { klass -> klass is FirRegularClass && klass.isExpect } } -internal fun isInsideExternalClass(containingClass: FirRegularClass, context: CheckerContext): Boolean { - return isInsideSpecificClass(containingClass, context) { klass -> klass.isExternal } +internal fun isInsideExternalClass(containingClass: FirClass, context: CheckerContext): Boolean { + return isInsideSpecificClass(containingClass, context) { klass -> klass is FirRegularClass && klass.isExternal } } // Note that the class that contains the currently visiting declaration will *not* be in the context's containing declarations *yet*. private inline fun isInsideSpecificClass( - containingClass: FirRegularClass, + containingClass: FirClass, context: CheckerContext, - predicate: (FirRegularClass) -> Boolean + predicate: (FirClass) -> Boolean ): Boolean { return predicate.invoke(containingClass) || context.containingDeclarations.asReversed().any { it is FirRegularClass && predicate.invoke(it) } } internal fun FirMemberDeclaration.isEffectivelyExpect( - containingClass: FirRegularClass?, + containingClass: FirClass?, context: CheckerContext, ): Boolean { if (this.isExpect) return true @@ -53,7 +53,7 @@ internal fun FirMemberDeclaration.isEffectivelyExpect( } internal fun FirMemberDeclaration.isEffectivelyExternal( - containingClass: FirRegularClass?, + containingClass: FirClass?, context: CheckerContext, ): Boolean { if (this.isExternal) return true @@ -93,7 +93,7 @@ internal fun checkExpectDeclarationVisibilityAndBody( // Matched FE 1.0's [DeclarationsChecker#checkPropertyInitializer]. internal fun checkPropertyInitializer( - containingClass: FirRegularClass?, + containingClass: FirClass?, property: FirProperty, modifierList: FirModifierList?, isInitialized: Boolean, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt index a671e8ed350..4f586cb00ed 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt @@ -18,8 +18,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.lexer.KtTokens // See old FE's [DeclarationsChecker] -object FirMemberFunctionsChecker : FirRegularClassChecker() { - override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { +object FirMemberFunctionsChecker : FirClassChecker() { + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { for (member in declaration.declarations) { if (member is FirSimpleFunction) { checkFunction(declaration, member, context, reporter) @@ -28,7 +28,7 @@ object FirMemberFunctionsChecker : FirRegularClassChecker() { } private fun checkFunction( - containingDeclaration: FirRegularClass, + containingDeclaration: FirClass, function: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter @@ -41,7 +41,7 @@ object FirMemberFunctionsChecker : FirRegularClassChecker() { val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList val isAbstract = function.isAbstract || hasAbstractModifier if (isAbstract) { - if (!containingDeclaration.canHaveAbstractDeclaration) { + if (containingDeclaration is FirRegularClass && !containingDeclaration.canHaveAbstractDeclaration) { reporter.reportOn( source, FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt index 251c2511bbc..65b72ffa9f8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt @@ -30,8 +30,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.lexer.KtTokens // See old FE's [DeclarationsChecker] -object FirMemberPropertiesChecker : FirRegularClassChecker() { - override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { +object FirMemberPropertiesChecker : FirClassChecker() { + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { val memberPropertySymbols = declaration.declarations.filterIsInstance().map { it.symbol }.toSet() val initializedInConstructor = mutableMapOf().withDefault { EventOccurrencesRange.ZERO } @@ -59,7 +59,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { } private fun collectPropertyInitialization( - klass: FirRegularClass, + klass: FirClass, memberPropertySymbols: Set, initializedInConstructor: MutableMap, initializedInInitOrOtherProperty: MutableMap @@ -144,7 +144,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { } private fun checkProperty( - containingDeclaration: FirRegularClass, + containingDeclaration: FirClass, property: FirProperty, isInitialized: Boolean, context: CheckerContext, @@ -182,7 +182,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { } if (isAbstract) { - if (!containingDeclaration.canHaveAbstractDeclaration) { + if (containingDeclaration is FirRegularClass && !containingDeclaration.canHaveAbstractDeclaration) { property.source?.let { reporter.reportOn( it, @@ -216,7 +216,12 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { } } - private fun FirRegularClass.collectDeadEndDeclarations(): Set { + private fun FirClass.collectDeadEndDeclarations(): Set { + val controlFlowGraphReference = when (this) { + is FirAnonymousObject -> this.controlFlowGraphReference + is FirRegularClass -> this.controlFlowGraphReference + else -> null + } val cfg = controlFlowGraphReference?.controlFlowGraph ?: return emptySet() return cfg.exitNode.incomingEdges.keys .map { it.fir } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.fir.kt index c1bae7ff55e..8c6aba4782d 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.fir.kt @@ -264,7 +264,7 @@ class ClassObject() { fun foo() { val a = object { val x : Int - val y : Int + val y : Int val z : Int init { x = 1 @@ -282,7 +282,7 @@ class TestObjectExpression() { fun foo() { val a = object { val x : Int - val y : Int + val y : Int init { if (true) x = 12