From ac074384893f3aaeeaabb8d60531915dc27d12bc Mon Sep 17 00:00:00 2001 From: vldf Date: Fri, 7 Aug 2020 17:10:23 +0300 Subject: [PATCH] [FIR] Speed up CFA-checkers --- .../kotlin/fir/analysis/CheckersComponent.kt | 6 ++-- ...bstractFirPropertyInitializationChecker.kt | 2 +- .../analysis/cfa/FirControlFlowAnalyzer.kt | 29 ++++++++++++++----- .../cfa/FirPropertyInitializationAnalyzer.kt | 3 +- .../declaration/DeclarationCheckers.kt | 4 +-- .../declaration/DefaultDeclarationCheckers.kt | 6 +++- .../ExtendedDeclarationCheckers.kt | 4 +-- .../extended/VariableAssignmentChecker.kt | 6 ++-- 8 files changed, 38 insertions(+), 22 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt index dd074dfd7ac..6ac63c98728 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent -import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* import org.jetbrains.kotlin.fir.analysis.checkers.expression.* @@ -71,7 +71,7 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() { get() = _constructorCheckers override val controlFlowAnalyserCheckers: List get() = _controlFlowAnalyserCheckers - override val variableAssignmentCfaBasedCheckers: List + override val variableAssignmentCfaBasedCheckers: List get() = _variableAssignmentCfaBasedCheckers private val _fileCheckers: MutableList = mutableListOf() @@ -80,7 +80,7 @@ private class ComposedDeclarationCheckers : DeclarationCheckers() { private val _regularClassCheckers: MutableList = mutableListOf() private val _constructorCheckers: MutableList = mutableListOf() private val _controlFlowAnalyserCheckers: MutableList = mutableListOf() - private val _variableAssignmentCfaBasedCheckers: MutableList = mutableListOf() + private val _variableAssignmentCfaBasedCheckers: MutableList = mutableListOf() fun register(checkers: DeclarationCheckers) { _fileCheckers += checkers.allFileCheckers diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt index 021aa714038..37249d3717e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/AbstractFirPropertyInitializationChecker.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -abstract class AbstractFirCfaPropertyAssignmentChecker { +abstract class AbstractFirPropertyInitializationChecker { abstract fun analyze( graph: ControlFlowGraph, reporter: DiagnosticReporter, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt index 0ff8ef5884d..cea30565043 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirControlFlowAnalyzer.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.declarations.FirClass 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.resolve.dfa.cfg.ControlFlowGraph class FirControlFlowAnalyzer(session: FirSession) { @@ -20,23 +21,35 @@ class FirControlFlowAnalyzer(session: FirSession) { fun analyzeClassInitializer(klass: FirClass<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { if (graph.owner != null) return - checkers.forEach { it.analyze(graph, reporter) } + cfaCheckers.forEach { it.analyze(graph, reporter) } } fun analyzeFunction(function: FirFunction<*>, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { if (graph.owner != null) return cfaCheckers.forEach { it.analyze(graph, reporter) } - - val properties = AbstractFirCfaPropertyAssignmentChecker.LocalPropertyCollector.collect(graph) - if (properties.isEmpty()) return - val data = AbstractFirCfaPropertyAssignmentChecker.DataCollector(properties).getData(graph) - - variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties) } + if (context.containingDeclarations.any { it is FirProperty || it is FirFunction<*> }) return + runAssignmentCfaCheckers(graph, reporter) } fun analyzePropertyInitializer(property: FirProperty, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { if (graph.owner != null) return - checkers.forEach { it.analyze(graph, reporter) } + + cfaCheckers.forEach { it.analyze(graph, reporter) } + runAssignmentCfaCheckers(graph, reporter) + } + + fun analyzePropertyAccessor(accessor: FirPropertyAccessor, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) { + if (graph.owner != null) return + + cfaCheckers.forEach { it.analyze(graph, reporter) } + runAssignmentCfaCheckers(graph, reporter) + } + + private fun runAssignmentCfaCheckers(graph: ControlFlowGraph, reporter: DiagnosticReporter) { + val properties = AbstractFirPropertyInitializationChecker.LocalPropertyCollector.collect(graph) + if (properties.isEmpty()) return + val data = AbstractFirPropertyInitializationChecker.DataCollector(properties).getData(graph) + variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt index 47551c013ae..c05c94b6ec1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt @@ -18,14 +18,13 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.QualifiedAccessNode import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol -object FirPropertyInitializationAnalyzer : AbstractFirCfaPropertyAssignmentChecker() { +object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChecker() { override fun analyze( graph: ControlFlowGraph, reporter: DiagnosticReporter, data: Map, PropertyInitializationInfo>, properties: Set ) { - // getting symbols of properties without initializers and non-variable symbols val localData = data.filter { val symbolFir = (it.key.fir as? FirVariableSymbol<*>)?.fir symbolFir == null || symbolFir.initializer == null && symbolFir.delegate == null diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt index e93050b625c..09ebff60267 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker abstract class DeclarationCheckers { @@ -19,7 +19,7 @@ abstract class DeclarationCheckers { open val regularClassCheckers: List = emptyList() open val constructorCheckers: List = emptyList() open val controlFlowAnalyserCheckers: List = emptyList() - open val variableAssignmentCfaBasedCheckers: List = emptyList() + open val variableAssignmentCfaBasedCheckers: List = emptyList() internal val allFileCheckers: List get() = fileCheckers + declarationCheckers internal val allMemberDeclarationCheckers: List get() = memberDeclarationCheckers + declarationCheckers diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt index d45d148d4ae..94afcb0dcb2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.cfa.FirCallsEffectAnalyzer import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer @@ -49,8 +50,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() { ) override val controlFlowAnalyserCheckers: List = listOf( - FirPropertyInitializationAnalyzer, FirCallsEffectAnalyzer, FirReturnsImpliesAnalyzer ) + + override val variableAssignmentCfaBasedCheckers: List = listOf( + FirPropertyInitializationAnalyzer + ) } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt index f584010011f..2d49c266293 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/ExtendedDeclarationCheckers.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.checkers.extended.* object ExtendedDeclarationCheckers : DeclarationCheckers() { @@ -20,7 +20,7 @@ object ExtendedDeclarationCheckers : DeclarationCheckers() { RedundantSetterParameterTypeChecker ) - override val variableAssignmentCfaBasedCheckers: List = listOf( + override val variableAssignmentCfaBasedCheckers: List = listOf( VariableAssignmentChecker ) } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt index 413dadf8b62..7d28cd13ed7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/VariableAssignmentChecker.kt @@ -9,7 +9,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.fir.FirFakeSourceElement import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirCfaPropertyAssignmentChecker +import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.cfa.TraverseDirection import org.jetbrains.kotlin.fir.analysis.cfa.traverse import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.toFirPsiSourceElement import org.jetbrains.kotlin.psi.KtProperty -object VariableAssignmentChecker : AbstractFirCfaPropertyAssignmentChecker() { +object VariableAssignmentChecker : AbstractFirPropertyInitializationChecker() { override fun analyze( graph: ControlFlowGraph, reporter: DiagnosticReporter, @@ -64,7 +64,7 @@ object VariableAssignmentChecker : AbstractFirCfaPropertyAssignmentChecker() { destructuringCanBeVal = false } lastDestructuredVariables-- - } else if (canBeVal(symbol, value) && symbol.fir.delegate == null) { + } else if (canBeVal(symbol, value) && symbol.fir.delegate == null ) { reporter.report(source, FirErrors.CAN_BE_VAL) } }