K2 Scripting: add FirScript to declaration checkers
This commit is contained in:
committed by
Space Team
parent
b7057eb22f
commit
8c30f3b2bc
+1
@@ -79,6 +79,7 @@ fun main(args: Array<String>) {
|
||||
alias<FirRegularClass>("RegularClassChecker")
|
||||
alias<FirConstructor>("ConstructorChecker")
|
||||
alias<FirFile>("FileChecker")
|
||||
alias<FirScript>("ScriptChecker")
|
||||
alias<FirTypeParameter>("FirTypeParameterChecker")
|
||||
alias<FirTypeAlias>("TypeAliasChecker")
|
||||
alias<FirAnonymousFunction>("AnonymousFunctionChecker")
|
||||
|
||||
+4
@@ -35,6 +35,8 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
get() = _constructorCheckers
|
||||
override val fileCheckers: Set<FirFileChecker>
|
||||
get() = _fileCheckers
|
||||
override val scriptCheckers: Set<FirScriptChecker>
|
||||
get() = _scriptCheckers
|
||||
override val typeParameterCheckers: Set<FirTypeParameterChecker>
|
||||
get() = _typeParameterCheckers
|
||||
override val typeAliasCheckers: Set<FirTypeAliasChecker>
|
||||
@@ -68,6 +70,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
|
||||
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
|
||||
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
|
||||
private val _scriptCheckers: MutableSet<FirScriptChecker> = mutableSetOf()
|
||||
private val _typeParameterCheckers: MutableSet<FirTypeParameterChecker> = mutableSetOf()
|
||||
private val _typeAliasCheckers: MutableSet<FirTypeAliasChecker> = mutableSetOf()
|
||||
private val _anonymousFunctionCheckers: MutableSet<FirAnonymousFunctionChecker> = mutableSetOf()
|
||||
@@ -92,6 +95,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
_regularClassCheckers += checkers.regularClassCheckers
|
||||
_constructorCheckers += checkers.constructorCheckers
|
||||
_fileCheckers += checkers.fileCheckers
|
||||
_scriptCheckers += checkers.scriptCheckers
|
||||
_typeParameterCheckers += checkers.typeParameterCheckers
|
||||
_typeAliasCheckers += checkers.typeAliasCheckers
|
||||
_anonymousFunctionCheckers += checkers.anonymousFunctionCheckers
|
||||
|
||||
+2
@@ -29,6 +29,7 @@ abstract class DeclarationCheckers {
|
||||
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
|
||||
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
|
||||
open val fileCheckers: Set<FirFileChecker> = emptySet()
|
||||
open val scriptCheckers: Set<FirScriptChecker> = emptySet()
|
||||
open val typeParameterCheckers: Set<FirTypeParameterChecker> = emptySet()
|
||||
open val typeAliasCheckers: Set<FirTypeAliasChecker> = emptySet()
|
||||
open val anonymousFunctionCheckers: Set<FirAnonymousFunctionChecker> = emptySet()
|
||||
@@ -52,6 +53,7 @@ abstract class DeclarationCheckers {
|
||||
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> by lazy { regularClassCheckers + classCheckers + classLikeCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> by lazy { constructorCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> by lazy { fileCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allScriptCheckers: Set<FirScriptChecker> by lazy { scriptCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> by lazy { typeParameterCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allTypeAliasCheckers: Set<FirTypeAliasChecker> by lazy { typeAliasCheckers + classLikeCheckers + basicDeclarationCheckers }
|
||||
@CheckersComponentInternal internal val allAnonymousFunctionCheckers: Set<FirAnonymousFunctionChecker> by lazy { anonymousFunctionCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
|
||||
|
||||
+2
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirScript
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
@@ -40,6 +41,7 @@ typealias FirClassChecker = FirDeclarationChecker<FirClass>
|
||||
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
|
||||
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
|
||||
typealias FirFileChecker = FirDeclarationChecker<FirFile>
|
||||
typealias FirScriptChecker = FirDeclarationChecker<FirScript>
|
||||
typealias FirTypeParameterChecker = FirDeclarationChecker<FirTypeParameter>
|
||||
typealias FirTypeAliasChecker = FirDeclarationChecker<FirTypeAlias>
|
||||
typealias FirAnonymousFunctionChecker = FirDeclarationChecker<FirAnonymousFunction>
|
||||
|
||||
+5
@@ -157,6 +157,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirTopLevelPropertiesChecker,
|
||||
)
|
||||
|
||||
override val scriptCheckers: Set<FirScriptChecker>
|
||||
get() = setOf(
|
||||
FirScriptPropertiesChecker
|
||||
)
|
||||
|
||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
||||
get() = setOf(
|
||||
FirCallsEffectAnalyzer,
|
||||
|
||||
+39
-33
@@ -34,44 +34,50 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
// See old FE's [DeclarationsChecker]
|
||||
object FirTopLevelPropertiesChecker : FirFileChecker() {
|
||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
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)
|
||||
}
|
||||
val topLevelProperties = declaration.declarations.filterIsInstance<FirProperty>()
|
||||
checkFileLikeDeclaration(declaration, topLevelProperties, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(
|
||||
topLevelProperties: List<FirProperty>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
): PropertyInitializationInfo? {
|
||||
val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null
|
||||
|
||||
val propertySymbols = topLevelProperties.mapNotNullTo(mutableSetOf()) { declaration ->
|
||||
declaration.symbol.takeIf { it.requiresInitialization(isForInitialization = true) }
|
||||
}
|
||||
if (propertySymbols.isEmpty()) return null
|
||||
|
||||
// TODO, KT-59803: merge with `FirPropertyInitializationAnalyzer` for fewer passes.
|
||||
val data = PropertyInitializationInfoData(propertySymbols, receiver = null, graph)
|
||||
data.checkPropertyAccesses(isForInitialization = true, context, reporter)
|
||||
return data.getValue(graph.exitNode)[NormalPath]
|
||||
object FirScriptPropertiesChecker : FirScriptChecker() {
|
||||
override fun check(declaration: FirScript, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val topLevelProperties = declaration.statements.filterIsInstance<FirProperty>()
|
||||
checkFileLikeDeclaration(declaration, topLevelProperties, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFileLikeDeclaration(
|
||||
declaration: FirDeclaration,
|
||||
topLevelProperties: List<FirProperty>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirDeclaration.collectionInitializationInfo(
|
||||
topLevelProperties: List<FirProperty>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
): PropertyInitializationInfo? {
|
||||
val graph = (this as? FirControlFlowGraphOwner)?.controlFlowGraphReference?.controlFlowGraph ?: return null
|
||||
|
||||
val propertySymbols = topLevelProperties.mapNotNullTo(mutableSetOf()) { declaration ->
|
||||
declaration.symbol.takeIf { it.requiresInitialization(isForInitialization = true) }
|
||||
}
|
||||
if (propertySymbols.isEmpty()) return null
|
||||
|
||||
// TODO, KT-59803: merge with `FirPropertyInitializationAnalyzer` for fewer passes.
|
||||
val data = PropertyInitializationInfoData(propertySymbols, receiver = null, graph)
|
||||
data.checkPropertyAccesses(isForInitialization = true, context, reporter)
|
||||
return data.getValue(graph.exitNode)[NormalPath]
|
||||
}
|
||||
|
||||
// Matched FE 1.0's [DeclarationsChecker#checkPropertyInitializer].
|
||||
internal fun checkPropertyInitializer(
|
||||
containingClass: FirClass?,
|
||||
|
||||
+6
@@ -44,6 +44,12 @@ class ControlFlowAnalysisDiagnosticComponent(
|
||||
analyze(file, data)
|
||||
}
|
||||
|
||||
// ------------------------------- File -------------------------------
|
||||
|
||||
override fun visitScript(script: FirScript, data: CheckerContext) {
|
||||
analyze(script, data)
|
||||
}
|
||||
|
||||
// ------------------------------- Class initializer -------------------------------
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ class DeclarationCheckersDiagnosticComponent(
|
||||
}
|
||||
|
||||
override fun visitScript(script: FirScript, data: CheckerContext) {
|
||||
checkers.allBasicDeclarationCheckers.check(script, data)
|
||||
checkers.allScriptCheckers.check(script, data)
|
||||
}
|
||||
|
||||
override fun visitCodeFragment(codeFragment: FirCodeFragment, data: CheckerContext) {
|
||||
|
||||
Reference in New Issue
Block a user