From 9278dee1a49533a33591b78abd04a3c1a315e7d9 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 12 Jan 2015 14:15:34 +0300 Subject: [PATCH] Pseudocode: Bind nondeterministic jump caused by local declaration to declaration iself instead of its parent element #KT-6261 Fixed #KT-6416 Fixed --- .../kotlin/cfg/JetControlFlowProcessor.java | 5 +-- .../local/localFunction.instructions | 40 +++++++++++++++++++ .../cfg/declarations/local/localFunction.kt | 5 +++ .../declarations/local/localFunction.values | 17 ++++++++ .../kotlin/cfg/ControlFlowTestGenerated.java | 6 +++ .../kotlin/cfg/PseudoValueTestGenerated.java | 6 +++ ...calFunctionInTheMiddleSimpleControlFlow.kt | 6 +++ ...ctionInTheMiddleSimpleControlFlow.kt.after | 10 +++++ .../localFunctionInTheMiddleUnusedVar.kt | 5 +++ ...localFunctionInTheMiddleUnusedVar.kt.after | 9 +++++ .../basic/localFunctionInTheMiddleUsedVar.kt | 9 +++++ .../localFunctionInTheMiddleUsedVar.kt.after | 13 ++++++ .../JetExtractionTestGenerated.java | 18 +++++++++ 13 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/cfg/declarations/local/localFunction.instructions create mode 100644 compiler/testData/cfg/declarations/local/localFunction.kt create mode 100644 compiler/testData/cfg/declarations/local/localFunction.values create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt.after create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt.after create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt create mode 100644 idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java index 4ac0df08b41..d48c9e8731a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java @@ -114,12 +114,9 @@ public class JetControlFlowProcessor { } private void processLocalDeclaration(@NotNull JetDeclaration subroutine) { - JetElement parent = PsiTreeUtil.getParentOfType(subroutine, JetElement.class); - assert parent != null; - Label afterDeclaration = builder.createUnboundLabel("after local declaration"); - builder.nondeterministicJump(afterDeclaration, parent, null); + builder.nondeterministicJump(afterDeclaration, subroutine, null); generate(subroutine); builder.bindLabel(afterDeclaration); } diff --git a/compiler/testData/cfg/declarations/local/localFunction.instructions b/compiler/testData/cfg/declarations/local/localFunction.instructions new file mode 100644 index 00000000000..1633a229229 --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localFunction.instructions @@ -0,0 +1,40 @@ +== test == +fun test(): Int { + val j = 1 + fun local() = 1 + return local() +} +--------------------- +L0: + 1 + 2 mark({ val j = 1 fun local() = 1 return local() }) + v(val j = 1) + r(1) -> + w(j|) + jmp?(L2) NEXT:[mark(local()), d(fun local() = 1)] + d(fun local() = 1) NEXT:[] +L2 [after local declaration]: + mark(local()) PREV:[jmp?(L2)] + call(local(), local) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d(fun local() = 1)] +===================== +== local == +fun local() = 1 +--------------------- +L3: + 3 + r(1) -> + ret(*|) L4 +L4: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/declarations/local/localFunction.kt b/compiler/testData/cfg/declarations/local/localFunction.kt new file mode 100644 index 00000000000..bda09de40db --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localFunction.kt @@ -0,0 +1,5 @@ +fun test(): Int { + val j = 1 + fun local() = 1 + return local() +} \ No newline at end of file diff --git a/compiler/testData/cfg/declarations/local/localFunction.values b/compiler/testData/cfg/declarations/local/localFunction.values new file mode 100644 index 00000000000..08939152614 --- /dev/null +++ b/compiler/testData/cfg/declarations/local/localFunction.values @@ -0,0 +1,17 @@ +== test == +fun test(): Int { + val j = 1 + fun local() = 1 + return local() +} +--------------------- +1 : Int NEW: r(1) -> +local() : Int NEW: call(local(), local) -> +return local() !: * +{ val j = 1 fun local() = 1 return local() } !: * COPY +===================== +== local == +fun local() = 1 +--------------------- +1 : Int NEW: r(1) -> +===================== diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index 644b330e0b9..afdc78a08da 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -369,6 +369,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { doTest(fileName); } + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); + doTest(fileName); + } + @TestMetadata("localProperty.kt") public void testLocalProperty() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localProperty.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index 96b2456adc9..2833d5118e7 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -372,6 +372,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { doTest(fileName); } + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); + doTest(fileName); + } + @TestMetadata("localProperty.kt") public void testLocalProperty() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localProperty.kt"); diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt new file mode 100644 index 00000000000..b1053efb644 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt @@ -0,0 +1,6 @@ +fun test1(): Int { + val foo = 1 + fun bar() = 2 + + return 3 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt.after b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt.after new file mode 100644 index 00000000000..87bbf7d5445 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt.after @@ -0,0 +1,10 @@ +fun test1(): Int { + return i() +} + +private fun i(): Int { + val foo = 1 + fun bar() = 2 + + return 3 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt new file mode 100644 index 00000000000..877ffdb64c8 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt @@ -0,0 +1,5 @@ +fun test(): Int { + val j = 1 + fun local() = 1 + return local() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt.after b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt.after new file mode 100644 index 00000000000..7e7aceaebd4 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt.after @@ -0,0 +1,9 @@ +fun test(): Int { + return i() +} + +private fun i(): Int { + val j = 1 + fun local() = 1 + return local() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt new file mode 100644 index 00000000000..60f4a06b919 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt @@ -0,0 +1,9 @@ +fun test(): Int { + val foo = 1 + fun bar() = 2 + + return when (foo) { + 1 -> 1 + else -> 2 + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt.after b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt.after new file mode 100644 index 00000000000..f6a7e1cf408 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt.after @@ -0,0 +1,13 @@ +fun test(): Int { + return i() +} + +private fun i(): Int { + val foo = 1 + fun bar() = 2 + + return when (foo) { + 1 -> 1 + else -> 2 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java index 999ab4140c5..4bab4d610d5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java @@ -414,6 +414,24 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest(fileName); } + @TestMetadata("localFunctionInTheMiddleSimpleControlFlow.kt") + public void testLocalFunctionInTheMiddleSimpleControlFlow() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleSimpleControlFlow.kt"); + doExtractFunctionTest(fileName); + } + + @TestMetadata("localFunctionInTheMiddleUnusedVar.kt") + public void testLocalFunctionInTheMiddleUnusedVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUnusedVar.kt"); + doExtractFunctionTest(fileName); + } + + @TestMetadata("localFunctionInTheMiddleUsedVar.kt") + public void testLocalFunctionInTheMiddleUsedVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/localFunctionInTheMiddleUsedVar.kt"); + doExtractFunctionTest(fileName); + } + @TestMetadata("localFunctionRef.kt") public void testLocalFunctionRef() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/localFunctionRef.kt");