diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt index c2be84b6b69..ad5067bb63c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt @@ -34,29 +34,32 @@ import org.jetbrains.kotlin.lexer.KtTokens // See old FE's [DeclarationsChecker] object FirTopLevelPropertiesChecker : FirFileChecker() { override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) { - val info = declaration.collectionInitializationInfo(context, reporter) - for (innerDeclaration in declaration.declarations) { - if (innerDeclaration is FirProperty) { - val symbol = innerDeclaration.symbol - val isDefinitelyAssigned = info?.get(symbol)?.isDefinitelyVisited() == true - checkProperty(containingDeclaration = null, innerDeclaration, isDefinitelyAssigned, context, reporter, reachable = true) - } + val topLevelProperties = declaration.effectiveTopLevelProperties + val info = declaration.collectionInitializationInfo(topLevelProperties, context, reporter) + for (topLevelProperty in topLevelProperties) { + val symbol = topLevelProperty.symbol + val isDefinitelyAssigned = info?.get(symbol)?.isDefinitelyVisited() == true + checkProperty(containingDeclaration = null, topLevelProperty, isDefinitelyAssigned, context, reporter, reachable = true) } } + /** + * Scripts are nested as a single declaration under [FirFile]s and contain their own statements. To properly check all "top-level" + * properties, script statements need to be unwrapped. + */ + private val FirFile.effectiveTopLevelProperties: List + get() = when (val script = declarations.singleOrNull()) { + is FirScript -> script.statements.filterIsInstance() + else -> declarations.filterIsInstance() + } + private fun FirFile.collectionInitializationInfo( + topLevelProperties: List, context: CheckerContext, reporter: DiagnosticReporter, ): PropertyInitializationInfo? { val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null - // Scripts are nested as a single declaration under FirFiles and contain their own statements. To properly check all "top-level" - // properties, script statements need to be unwrapped. - val topLevelProperties = when (val script = declarations.singleOrNull()) { - is FirScript -> script.statements.filterIsInstance() - else -> declarations.filterIsInstance() - } - val propertySymbols = topLevelProperties.mapNotNullTo(mutableSetOf()) { declaration -> declaration.symbol.takeIf { it.requiresInitialization(isForInitialization = true) } } diff --git a/compiler/testData/diagnostics/tests/script/topLevelPropertiesWithGetSet.fir.kts b/compiler/testData/diagnostics/tests/script/topLevelPropertiesWithGetSet.fir.kts index ef352763440..8e843c0640a 100644 --- a/compiler/testData/diagnostics/tests/script/topLevelPropertiesWithGetSet.fir.kts +++ b/compiler/testData/diagnostics/tests/script/topLevelPropertiesWithGetSet.fir.kts @@ -16,10 +16,10 @@ get() = 42 val testValLineBreakNoType get() = 42 -val testValLineBreakSemi: Int; +val testValLineBreakSemi: Int; get() = 42 -val testValLineBreakSemiNoType; +val testValLineBreakSemiNoType; get() = 42 var testVarLineBreak: Int @@ -30,10 +30,10 @@ var String.testExtVarLineBreak: Int get() = 42 set(value) {} -var testVarLineBreakSemi: Int; +var testVarLineBreakSemi: Int; get() = 42 set(value) {} -var String.testExtVarLineBreakSemi: Int; +var String.testExtVarLineBreakSemi: Int; get() = 42 set(value) {} diff --git a/compiler/testData/diagnostics/tests/script/topLevelPropertyInitialization.fir.kts b/compiler/testData/diagnostics/tests/script/topLevelPropertyInitialization.fir.kts index 0715e82bf0c..dc6d72860a0 100644 --- a/compiler/testData/diagnostics/tests/script/topLevelPropertyInitialization.fir.kts +++ b/compiler/testData/diagnostics/tests/script/topLevelPropertyInitialization.fir.kts @@ -32,9 +32,9 @@ val d: String by simpleDelegate(d) val e: String by inPlaceDelegate { e } val f: String by notInPlaceDelegate { f } -val g: Int +val g: Int val h = 1.also { g = 2 } -val i: Int +val i: Int val j by lazy { i = 2; 1 } val k: Int get() {