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