[FIR] Fix top-level property initialization checks in scripts
- While `collectionInitializationInfo` unwrapped a script's top-level declarations, `check` forgot to do it, so a script effectively had no top-level properties in the mind of the checker. ^KT-63286 fixed
This commit is contained in:
committed by
Space Team
parent
1cc2390af6
commit
730f98ba38
+17
-14
@@ -34,29 +34,32 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
// See old FE's [DeclarationsChecker]
|
// See old FE's [DeclarationsChecker]
|
||||||
object FirTopLevelPropertiesChecker : FirFileChecker() {
|
object FirTopLevelPropertiesChecker : FirFileChecker() {
|
||||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val info = declaration.collectionInitializationInfo(context, reporter)
|
val topLevelProperties = declaration.effectiveTopLevelProperties
|
||||||
for (innerDeclaration in declaration.declarations) {
|
val info = declaration.collectionInitializationInfo(topLevelProperties, context, reporter)
|
||||||
if (innerDeclaration is FirProperty) {
|
for (topLevelProperty in topLevelProperties) {
|
||||||
val symbol = innerDeclaration.symbol
|
val symbol = topLevelProperty.symbol
|
||||||
val isDefinitelyAssigned = info?.get(symbol)?.isDefinitelyVisited() == true
|
val isDefinitelyAssigned = info?.get(symbol)?.isDefinitelyVisited() == true
|
||||||
checkProperty(containingDeclaration = null, innerDeclaration, isDefinitelyAssigned, context, reporter, reachable = 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<FirProperty>
|
||||||
|
get() = when (val script = declarations.singleOrNull()) {
|
||||||
|
is FirScript -> script.statements.filterIsInstance<FirProperty>()
|
||||||
|
else -> declarations.filterIsInstance<FirProperty>()
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirFile.collectionInitializationInfo(
|
private fun FirFile.collectionInitializationInfo(
|
||||||
|
topLevelProperties: List<FirProperty>,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
): PropertyInitializationInfo? {
|
): PropertyInitializationInfo? {
|
||||||
val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null
|
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<FirProperty>()
|
|
||||||
else -> declarations.filterIsInstance<FirProperty>()
|
|
||||||
}
|
|
||||||
|
|
||||||
val propertySymbols = topLevelProperties.mapNotNullTo(mutableSetOf()) { declaration ->
|
val propertySymbols = topLevelProperties.mapNotNullTo(mutableSetOf()) { declaration ->
|
||||||
declaration.symbol.takeIf { it.requiresInitialization(isForInitialization = true) }
|
declaration.symbol.takeIf { it.requiresInitialization(isForInitialization = true) }
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -16,10 +16,10 @@ get() = 42
|
|||||||
val testValLineBreakNoType
|
val testValLineBreakNoType
|
||||||
get() = 42
|
get() = 42
|
||||||
|
|
||||||
val testValLineBreakSemi: Int;
|
<!MUST_BE_INITIALIZED!>val testValLineBreakSemi: Int<!>;
|
||||||
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
||||||
|
|
||||||
val testValLineBreakSemiNoType;
|
<!MUST_BE_INITIALIZED!>val testValLineBreakSemiNoType<!>;
|
||||||
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
||||||
|
|
||||||
var testVarLineBreak: Int
|
var testVarLineBreak: Int
|
||||||
@@ -30,10 +30,10 @@ var String.testExtVarLineBreak: Int
|
|||||||
get() = 42
|
get() = 42
|
||||||
set(value) {}
|
set(value) {}
|
||||||
|
|
||||||
var testVarLineBreakSemi: Int;
|
<!MUST_BE_INITIALIZED!>var testVarLineBreakSemi: Int<!>;
|
||||||
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
||||||
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {}
|
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {}
|
||||||
|
|
||||||
var String.testExtVarLineBreakSemi: Int;
|
<!EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT!>var String.testExtVarLineBreakSemi: Int<!>;
|
||||||
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
<!VARIABLE_EXPECTED!><!UNRESOLVED_REFERENCE!>get<!>()<!> = 42
|
||||||
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {}
|
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {}
|
||||||
|
|||||||
+2
-2
@@ -32,9 +32,9 @@ val d: String by simpleDelegate(d)
|
|||||||
val e: String by inPlaceDelegate { e }
|
val e: String by inPlaceDelegate { e }
|
||||||
val f: String by notInPlaceDelegate { f }
|
val f: String by notInPlaceDelegate { f }
|
||||||
|
|
||||||
val g: Int
|
<!MUST_BE_INITIALIZED!>val g: Int<!>
|
||||||
val h = 1.also { <!VAL_REASSIGNMENT!>g<!> = 2 }
|
val h = 1.also { <!VAL_REASSIGNMENT!>g<!> = 2 }
|
||||||
val i: Int
|
<!MUST_BE_INITIALIZED!>val i: Int<!>
|
||||||
val j by lazy { <!VAL_REASSIGNMENT!>i<!> = 2; 1 }
|
val j by lazy { <!VAL_REASSIGNMENT!>i<!> = 2; 1 }
|
||||||
val k: Int
|
val k: Int
|
||||||
get() {
|
get() {
|
||||||
|
|||||||
Reference in New Issue
Block a user