FIR: remove unused code from LocalPropertyAndCapturedWriteCollector

This commit is contained in:
pyos
2023-01-20 11:46:03 +01:00
committed by teamcity
parent 99e51f6940
commit 6040053961
6 changed files with 14 additions and 81 deletions
@@ -18,7 +18,6 @@ abstract class AbstractFirPropertyInitializationChecker {
reporter: DiagnosticReporter,
data: PropertyInitializationInfoData,
properties: Set<FirPropertySymbol>,
capturedWrites: Set<FirVariableAssignment>,
context: CheckerContext
)
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoData
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.checkPropertyAccesses
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.requiresInitialization
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -20,7 +19,6 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
reporter: DiagnosticReporter,
data: PropertyInitializationInfoData,
properties: Set<FirPropertySymbol>,
capturedWrites: Set<FirVariableAssignment>,
context: CheckerContext
) = graph.checkPropertyAccesses(properties.filterTo(mutableSetOf()) { it.requiresInitialization }, null, context, reporter, data)
}
@@ -1,72 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.cfa.util
import org.jetbrains.kotlin.contracts.description.isInPlace
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
// TODO: this should be a FIR tree visitor, not a control flow graph visitor.
class LocalPropertyAndCapturedWriteCollector private constructor() : ControlFlowGraphVisitorVoid() {
companion object {
fun collect(graph: ControlFlowGraph): Pair<Set<FirPropertySymbol>, Set<FirVariableAssignment>> {
val collector = LocalPropertyAndCapturedWriteCollector()
graph.traverse(collector)
return collector.symbols.keys to collector.capturedWrites
}
}
// Mapping from a property symbol to its declaration context
// `true` if the (local) property is declared in the currently visited function.
// `false` if it is declared in a lambda or a local function (inside the currently visited function).
private val symbols: MutableMap<FirPropertySymbol, Boolean> = mutableMapOf()
private val lambdaOrLocalFunctionStack: MutableList<FirFunction> = mutableListOf()
private val capturedWrites: MutableSet<FirVariableAssignment> = mutableSetOf()
override fun visitNode(node: CFGNode<*>) {}
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
symbols[node.fir.symbol] = lambdaOrLocalFunctionStack.lastOrNull() == null
}
override fun visitSplitPostponedLambdasNode(node: SplitPostponedLambdasNode) {
lambdaOrLocalFunctionStack.addAll(node.lambdas)
}
override fun visitAnonymousFunctionExpressionNode(node: AnonymousFunctionExpressionNode) {
lambdaOrLocalFunctionStack.add(node.fir.anonymousFunction)
}
override fun visitLocalFunctionDeclarationNode(node: LocalFunctionDeclarationNode) {
lambdaOrLocalFunctionStack.add(node.fir)
}
override fun visitFunctionExitNode(node: FunctionExitNode) {
lambdaOrLocalFunctionStack.remove(node.fir)
}
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: return
// Check if this variable assignment is inside a lambda or a local function.
if (lambdaOrLocalFunctionStack.isEmpty()) return
// Check if the assigned variable doesn't belong to any lambda or local function.
if (symbol !in symbols || symbols[symbol] == false) return
// If all nested declarations are lambdas that are invoked in-place (according to the contract),
// this variable assignment is not a captured write.
if (lambdaOrLocalFunctionStack.all { it is FirAnonymousFunction && it.invocationKind.isInPlace }) return
capturedWrites.add(node.fir)
}
}
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoData
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -27,7 +26,6 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
reporter: DiagnosticReporter,
data: PropertyInitializationInfoData,
properties: Set<FirPropertySymbol>,
capturedWrites: Set<FirVariableAssignment>,
context: CheckerContext
) {
val unprocessedProperties = mutableSetOf<FirPropertySymbol>()
@@ -36,7 +36,6 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
reporter: DiagnosticReporter,
data: PropertyInitializationInfoData,
properties: Set<FirPropertySymbol>,
capturedWrites: Set<FirVariableAssignment>,
context: CheckerContext
) {
val ownData = ValueWritesWithoutReading(context.session, properties).getData(graph)
@@ -10,10 +10,13 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.cfa.util.LocalPropertyAndCapturedWriteCollector
import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoData
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraphVisitorVoid
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.VariableDeclarationNode
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
class ControlFlowAnalysisDiagnosticComponent(
session: FirSession,
@@ -28,10 +31,10 @@ class ControlFlowAnalysisDiagnosticComponent(
if (graph.isSubGraph) return
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
val (properties, capturedWrites) = LocalPropertyAndCapturedWriteCollector.collect(graph)
val properties = mutableSetOf<FirPropertySymbol>().apply { graph.traverse(LocalPropertyCollector(this)) }
if (properties.isNotEmpty()) {
val data = PropertyInitializationInfoData(properties, receiver = null, graph)
variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties, capturedWrites, context) }
variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties, context) }
}
}
@@ -68,4 +71,12 @@ class ControlFlowAnalysisDiagnosticComponent(
override fun visitConstructor(constructor: FirConstructor, data: CheckerContext) {
analyze(constructor, data)
}
private class LocalPropertyCollector(private val result: MutableSet<FirPropertySymbol>) : ControlFlowGraphVisitorVoid() {
override fun visitNode(node: CFGNode<*>) {}
override fun visitVariableDeclarationNode(node: VariableDeclarationNode) {
result.add(node.fir.symbol)
}
}
}