[FIR] Add incoming edges to local class's property initializers

This commit is contained in:
Dmitriy Novozhilov
2020-03-30 10:19:20 +03:00
parent c223ae03ba
commit 3190793b62
3 changed files with 16 additions and 12 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.dfa.* import org.jetbrains.kotlin.fir.resolve.dfa.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.isNothing import org.jetbrains.kotlin.fir.types.isNothing
@@ -54,7 +55,7 @@ class ControlFlowGraphBuilder {
private val exitsFromCompletedPostponedAnonymousFunctions: MutableList<PostponedLambdaExitNode> = mutableListOf() private val exitsFromCompletedPostponedAnonymousFunctions: MutableList<PostponedLambdaExitNode> = mutableListOf()
private val enterToLocalClassesMembers: MutableMap<FirFunctionSymbol<*>, CFGNode<*>?> = mutableMapOf() private val enterToLocalClassesMembers: MutableMap<FirCallableSymbol<*>, CFGNode<*>?> = mutableMapOf()
var levelCounter: Int = 0 var levelCounter: Int = 0
private set private set
@@ -256,29 +257,29 @@ class ControlFlowGraphBuilder {
} }
fun prepareForLocalClassMembers(members: Collection<FirCallableMemberDeclaration<*>>) { fun prepareForLocalClassMembers(members: Collection<FirCallableMemberDeclaration<*>>) {
members.forEachFunction { members.forEachMember {
enterToLocalClassesMembers[it.symbol] = lastNodes.topOrNull() enterToLocalClassesMembers[it.symbol] = lastNodes.topOrNull()
} }
} }
fun cleanAfterForLocalClassMembers(members: Collection<FirCallableMemberDeclaration<*>>) { fun cleanAfterForLocalClassMembers(members: Collection<FirCallableMemberDeclaration<*>>) {
members.forEachFunction { members.forEachMember {
enterToLocalClassesMembers.remove(it.symbol) enterToLocalClassesMembers.remove(it.symbol)
} }
} }
private inline fun Collection<FirCallableMemberDeclaration<*>>.forEachFunction(block: (FirFunction<*>) -> Unit) { private inline fun Collection<FirCallableMemberDeclaration<*>>.forEachMember(block: (FirCallableDeclaration<*>) -> Unit) {
for (member in this) { for (member in this) {
for (function in member.unwrap()) { for (callableDeclaration in member.unwrap()) {
block(function) block(callableDeclaration)
} }
} }
} }
private fun FirCallableMemberDeclaration<*>.unwrap(): List<FirFunction<*>> = private fun FirCallableMemberDeclaration<*>.unwrap(): List<FirCallableDeclaration<*>> =
when (this) { when (this) {
is FirFunction<*> -> listOf(this) is FirFunction<*> -> listOf(this)
is FirProperty -> listOfNotNull(this.getter, this.setter) is FirProperty -> listOfNotNull(this.getter, this.setter, this)
else -> emptyList() else -> emptyList()
} }
@@ -332,6 +333,9 @@ class ControlFlowGraphBuilder {
val enterNode = createPropertyInitializerEnterNode(property) val enterNode = createPropertyInitializerEnterNode(property)
val exitNode = createPropertyInitializerExitNode(property) val exitNode = createPropertyInitializerExitNode(property)
topLevelVariableInitializerExitNodes.push(exitNode) topLevelVariableInitializerExitNodes.push(exitNode)
enterToLocalClassesMembers[property.symbol]?.let {
addEdge(it, enterNode, preferredKind = EdgeKind.Dfg)
}
exitNodes.push(exitNode) exitNodes.push(exitNode)
lexicalScopes.push(stackOf(enterNode)) lexicalScopes.push(stackOf(enterNode))
graph.enterNode = enterNode graph.enterNode = enterNode
@@ -11,7 +11,7 @@ fun test(del: Any?) {
if (del !is Del) return if (del !is Del) return
class Local { class Local {
val delegatedVal by <!INAPPLICABLE_CANDIDATE!>df<!>(del) val delegatedVal by df(del)
val delegatedVal1: Int by <!INAPPLICABLE_CANDIDATE!>df<!>(del) val delegatedVal1: Int by df(del)
} }
} }
@@ -2,10 +2,10 @@ fun test(x: Any?) {
if (x !is String) return if (x !is String) return
class C { class C {
val v = x.<!UNRESOLVED_REFERENCE!>length<!> val v = x.length
val vGet: Int val vGet: Int
get() = x.<!UNRESOLVED_REFERENCE!>length<!> get() = x.length
val s: String = x val s: String = x
} }