FIR checker: revisit per-label iterations to avoid !!
This commit is contained in:
committed by
Mikhail Glukhikh
parent
762e315ce3
commit
c959ad7911
@@ -128,15 +128,14 @@ class PropertyInitializationInfoCollector(private val localProperties: Set<FirPr
|
||||
}
|
||||
|
||||
internal fun <P : PathAwareControlFlowInfo<P, S>, S : ControlFlowInfo<S, K, EventOccurrencesRange>, K : Any> addRange(
|
||||
info: P,
|
||||
pathAwareInfo: P,
|
||||
key: K,
|
||||
range: EventOccurrencesRange,
|
||||
constructor: (PersistentMap<EdgeLabel, S>) -> P
|
||||
): P {
|
||||
var resultMap = persistentMapOf<EdgeLabel, S>()
|
||||
// before: { |-> { p1 |-> PI1 }, l1 |-> { p2 |-> PI2 } }
|
||||
for (label in info.keys) {
|
||||
val dataPerLabel = info[label]!!
|
||||
for ((label, dataPerLabel) in pathAwareInfo) {
|
||||
val existingKind = dataPerLabel[key] ?: EventOccurrencesRange.ZERO
|
||||
val kind = existingKind + range
|
||||
resultMap = resultMap.put(label, dataPerLabel.put(key, kind))
|
||||
|
||||
+3
-3
@@ -89,9 +89,9 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
||||
for ((symbol, effectDeclaration) in functionalTypeEffects) {
|
||||
graph.exitNode.previousCfgNodes.forEach { node ->
|
||||
val requiredRange = effectDeclaration.kind
|
||||
val info = invocationData.getValue(node)
|
||||
for (label in info.keys) {
|
||||
if (investigate(info.getValue(label), symbol, requiredRange, function, reporter)) {
|
||||
val pathAwareInfo = invocationData.getValue(node)
|
||||
for (info in pathAwareInfo.values) {
|
||||
if (investigate(info, symbol, requiredRange, function, reporter)) {
|
||||
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
||||
break
|
||||
}
|
||||
|
||||
+2
-2
@@ -49,8 +49,8 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
||||
if (symbol !in localProperties) return
|
||||
if (symbol.fir.isLateInit) return
|
||||
val pathAwareInfo = data.getValue(node)
|
||||
for (label in pathAwareInfo.keys) {
|
||||
if (investigate(pathAwareInfo[label]!!, symbol, node)) {
|
||||
for (info in pathAwareInfo.values) {
|
||||
if (investigate(info, symbol, node)) {
|
||||
// To avoid duplicate reports, stop investigating remaining paths if the property is not initialized at any path.
|
||||
break
|
||||
}
|
||||
|
||||
+7
-8
@@ -44,8 +44,8 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
|
||||
val variableSymbol = (node.fir.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol ?: return
|
||||
val dataPerNode = data[node] ?: return
|
||||
for (label in dataPerNode.keys) {
|
||||
val data = dataPerNode[label]!![variableSymbol] ?: continue
|
||||
for (dataPerLabel in dataPerNode.values) {
|
||||
val data = dataPerLabel[variableSymbol] ?: continue
|
||||
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
|
||||
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
|
||||
val source = node.fir.lValue.source
|
||||
@@ -60,8 +60,8 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
val variableSymbol = node.fir.symbol
|
||||
if (variableSymbol.isLoopIterator) return
|
||||
val dataPerNode = data[node] ?: return
|
||||
for (label in dataPerNode.keys) {
|
||||
val data = dataPerNode[label]!![variableSymbol] ?: continue
|
||||
for (dataPerLabel in dataPerNode.values) {
|
||||
val data = dataPerLabel[variableSymbol] ?: continue
|
||||
|
||||
val variableSource = variableSymbol.fir.source.takeIf { it?.elementType != KtNodeTypes.DESTRUCTURING_DECLARATION }
|
||||
when {
|
||||
@@ -242,14 +242,13 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
}
|
||||
|
||||
private fun update(
|
||||
info: PathAwareVariableStatusInfo,
|
||||
pathAwareInfo: PathAwareVariableStatusInfo,
|
||||
symbol: FirPropertySymbol,
|
||||
updater: (VariableStatus?) -> VariableStatus?,
|
||||
): PathAwareVariableStatusInfo {
|
||||
var resultMap = persistentMapOf<EdgeLabel, VariableStatusInfo>()
|
||||
var changed = false
|
||||
for (label in info.keys) {
|
||||
val dataPerLabel = info[label]!!
|
||||
for ((label, dataPerLabel) in pathAwareInfo) {
|
||||
val v = updater.invoke(dataPerLabel[symbol])
|
||||
if (v != null) {
|
||||
resultMap = resultMap.put(label, dataPerLabel.put(symbol, v))
|
||||
@@ -258,7 +257,7 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
resultMap = resultMap.put(label, dataPerLabel)
|
||||
}
|
||||
}
|
||||
return if (changed) PathAwareVariableStatusInfo(resultMap) else info
|
||||
return if (changed) PathAwareVariableStatusInfo(resultMap) else pathAwareInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user