[FIR] Create CFG node for ::class calls
This commit is contained in:
committed by
teamcityserver
parent
c5ce52eef5
commit
9b00776dba
+5
@@ -64,6 +64,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/catchParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classCallInLambda.kt")
|
||||
public void testClassCallInLambda() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/classCallInLambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/companion.kt");
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
digraph classCallInLambda_kt {
|
||||
graph [nodesep=3]
|
||||
node [shape=box penwidth=2]
|
||||
edge [penwidth=2]
|
||||
|
||||
subgraph cluster_0 {
|
||||
color=red
|
||||
0 [label="Enter function test" style="filled" fillcolor=red];
|
||||
subgraph cluster_1 {
|
||||
color=blue
|
||||
1 [label="Enter block"];
|
||||
2 [label="Access variable R|<local>/x|"];
|
||||
3 [label="Postponed enter to lambda"];
|
||||
subgraph cluster_2 {
|
||||
color=blue
|
||||
11 [label="Enter function anonymousFunction" style="filled" fillcolor=red];
|
||||
subgraph cluster_3 {
|
||||
color=blue
|
||||
12 [label="Enter block"];
|
||||
13 [label="Access variable R|<local>/it|"];
|
||||
14 [label="::class call"];
|
||||
15 [label="Exit block"];
|
||||
}
|
||||
16 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||
}
|
||||
4 [label="Call arguments union" style="filled" fillcolor=yellow];
|
||||
5 [label="Postponed exit from lambda"];
|
||||
6 [label="Function call: R|<local>/x|.R|kotlin/let|<R|kotlin/String|, R|kotlin/reflect/KClass<out kotlin/String>|>(...)"];
|
||||
7 [label="Jump: ^test R|<local>/x|.R|kotlin/let|<R|kotlin/String|, R|kotlin/reflect/KClass<out kotlin/String>|>(<L> = let@fun <anonymous>(it: R|kotlin/String|): R|kotlin/reflect/KClass<out kotlin/String>| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
^ <getClass>(R|<local>/it|)
|
||||
}
|
||||
)"];
|
||||
8 [label="Stub" style="filled" fillcolor=gray];
|
||||
9 [label="Exit block" style="filled" fillcolor=gray];
|
||||
}
|
||||
10 [label="Exit function test" style="filled" fillcolor=red];
|
||||
}
|
||||
0 -> {1};
|
||||
1 -> {2};
|
||||
2 -> {3};
|
||||
3 -> {11};
|
||||
3 -> {5} [color=red];
|
||||
3 -> {11} [style=dashed];
|
||||
4 -> {6} [color=red];
|
||||
5 -> {6} [color=green];
|
||||
6 -> {7};
|
||||
7 -> {10};
|
||||
7 -> {8} [style=dotted];
|
||||
8 -> {9} [style=dotted];
|
||||
9 -> {10} [style=dotted];
|
||||
11 -> {12};
|
||||
12 -> {13};
|
||||
13 -> {14};
|
||||
14 -> {15};
|
||||
15 -> {16};
|
||||
16 -> {4} [color=red];
|
||||
16 -> {5} [color=green];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
FILE: classCallInLambda.kt
|
||||
public final fun test(x: R|kotlin/String|): R|kotlin/reflect/KClass<*>| {
|
||||
^test R|<local>/x|.R|kotlin/let|<R|kotlin/String|, R|kotlin/reflect/KClass<out kotlin/String>|>(<L> = let@fun <anonymous>(it: R|kotlin/String|): R|kotlin/reflect/KClass<out kotlin/String>| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
^ <getClass>(R|<local>/it|)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// WITH_STDLIB
|
||||
// DUMP_CFG
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun test(x: String): KClass<*> {
|
||||
return x.let { it::class }
|
||||
}
|
||||
+6
@@ -68,6 +68,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/catchParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classCallInLambda.kt")
|
||||
public void testClassCallInLambda() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/classCallInLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
|
||||
+6
@@ -68,6 +68,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/catchParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classCallInLambda.kt")
|
||||
public void testClassCallInLambda() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/classCallInLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
|
||||
@@ -1342,6 +1342,10 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
graphBuilder.exitCallableReference(callableReferenceAccess).mergeIncomingFlow()
|
||||
}
|
||||
|
||||
fun exitGetClassCall(getClassCall: FirGetClassCall) {
|
||||
graphBuilder.exitGetClassCall(getClassCall).mergeIncomingFlow()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ Utils ------------------------------------------------------
|
||||
|
||||
private fun getOrCreateLocalVariableAssignmentAnalyzer(firFunction: FirFunction): FirLocalVariableAssignmentAnalyzer? {
|
||||
|
||||
@@ -609,6 +609,12 @@ class CallableReferenceNode(
|
||||
}
|
||||
}
|
||||
|
||||
class GetClassCallNode(owner: ControlFlowGraph, override val fir: FirGetClassCall, level: Int, id: Int) : CFGNode<FirGetClassCall>(owner, level, id) {
|
||||
override fun <R, D> accept(visitor: ControlFlowGraphVisitor<R, D>, data: D): R {
|
||||
return visitor.visitGetClassCallNode(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
class DelegatedConstructorCallNode(
|
||||
owner: ControlFlowGraph,
|
||||
override val fir: FirDelegatedConstructorCall,
|
||||
|
||||
@@ -123,6 +123,7 @@ fun CFGNode<*>.render(): String =
|
||||
is ElvisExitNode -> "Exit ?:"
|
||||
|
||||
is CallableReferenceNode -> "Callable reference: ${fir.render(CfgRenderMode)}"
|
||||
is GetClassCallNode -> "::class call"
|
||||
|
||||
is AbstractBinaryExitNode -> throw IllegalStateException()
|
||||
},
|
||||
|
||||
+4
@@ -1121,6 +1121,10 @@ class ControlFlowGraphBuilder {
|
||||
return createCallableReferenceNode(callableReferenceAccess).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
fun exitGetClassCall(getClassCall: FirGetClassCall): GetClassCallNode {
|
||||
return createGetClassCallNode(getClassCall).also { addNewSimpleNode(it) }
|
||||
}
|
||||
|
||||
// ----------------------------------- Block -----------------------------------
|
||||
|
||||
fun enterInitBlock(initBlock: FirAnonymousInitializer): Pair<InitBlockEnterNode, CFGNode<*>?> {
|
||||
|
||||
+3
@@ -128,6 +128,9 @@ fun ControlFlowGraphBuilder.createFunctionCallNode(fir: FirFunctionCall): Functi
|
||||
fun ControlFlowGraphBuilder.createCallableReferenceNode(fir: FirCallableReferenceAccess): CallableReferenceNode =
|
||||
CallableReferenceNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
fun ControlFlowGraphBuilder.createGetClassCallNode(fir: FirGetClassCall): GetClassCallNode =
|
||||
GetClassCallNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
fun ControlFlowGraphBuilder.createDelegatedConstructorCallNode(fir: FirDelegatedConstructorCall): DelegatedConstructorCallNode =
|
||||
DelegatedConstructorCallNode(currentGraph, fir, levelCounter, createId())
|
||||
|
||||
|
||||
+4
@@ -299,6 +299,10 @@ abstract class ControlFlowGraphVisitor<out R, in D> {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitGetClassCallNode(node: GetClassCallNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
open fun visitDelegatedConstructorCallNode(node: DelegatedConstructorCallNode, data: D): R {
|
||||
return visitNode(node, data)
|
||||
}
|
||||
|
||||
+1
@@ -846,6 +846,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
buildResolvedTypeRef {
|
||||
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(typeOfExpression), false)
|
||||
}
|
||||
dataFlowAnalyzer.exitGetClassCall(transformedGetClassCall)
|
||||
return transformedGetClassCall
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -68,6 +68,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/catchParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classCallInLambda.kt")
|
||||
public void testClassCallInLambda() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/classCallInLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user