From 0a7d73ef6b5672e11be80929e7cc23912ab62e06 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 18 Nov 2014 15:39:38 +0300 Subject: [PATCH] Partial body resolve: more efficient handling of loops --- .../resolve/lazy/PartialBodyResolveFilter.kt | 36 +++++++++++++++++-- .../IfNullDoWhileWithBreak.dump | 3 ++ .../IfNullDoWhileWithBreak.kt | 15 ++++++++ .../IfNullForWithReturn.dump | 3 ++ .../partialBodyResolve/IfNullForWithReturn.kt | 14 ++++++++ .../IfNullWhileTrueWithBreak.dump | 3 ++ .../IfNullWhileTrueWithBreak.kt | 15 ++++++++ .../IfNullWhileWithReturn.dump | 3 ++ .../IfNullWhileWithReturn.kt | 15 ++++++++ .../PartialBodyResolveTestGenerated.java | 24 +++++++++++++ 10 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.dump create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.kt create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.dump create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.kt create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.dump create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.kt create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.dump create mode 100644 idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.kt diff --git a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt index f7aeda64838..655c2ad6a40 100644 --- a/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt +++ b/idea/ide-common/src/org/jetbrains/jet/lang/resolve/lazy/PartialBodyResolveFilter.kt @@ -212,6 +212,8 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J private fun collectAlwaysExitPoints(expression: JetExpression?): Collection { val result = ArrayList() expression?.accept(object : ControlFlowVisitor() { + var insideLoop = false + override fun visitReturnExpression(expression: JetReturnExpression) { result.add(expression) } @@ -220,13 +222,41 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J result.add(expression) } - //TODO: check loop entrance + override fun visitForExpression(loop: JetForExpression) { + loop.getLoopRange()?.accept(this) + // do not make sense to search exits inside for as not necessary enter it at all + } + + override fun visitWhileExpression(loop: JetWhileExpression) { + val condition = loop.getCondition() + if (condition.isTrueConstant()) { + insideLoop = true + loop.getBody()?.accept(this) + insideLoop = false + } + else { + // do not make sense to search exits inside for as not necessary enter it at all + condition?.accept(this) + } + } + + override fun visitDoWhileExpression(loop: JetDoWhileExpression) { + loop.getCondition()?.accept(this) + insideLoop = true + loop.getBody()?.accept(this) + insideLoop = false + } + override fun visitBreakExpression(expression: JetBreakExpression) { - result.add(expression) + if (!insideLoop || expression.getLabelName() != null) { + result.add(expression) + } } override fun visitContinueExpression(expression: JetContinueExpression) { - result.add(expression) + if (!insideLoop || expression.getLabelName() != null) { + result.add(expression) + } } }) return result diff --git a/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.dump b/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.dump new file mode 100644 index 00000000000..857da46776b --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.dump @@ -0,0 +1,3 @@ +Resolve target: val x: kotlin.Any? +Skipped statements: +if (x == null) { do { if (g()) break } while (f()) } diff --git a/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.kt b/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.kt new file mode 100644 index 00000000000..a5d6347e911 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.kt @@ -0,0 +1,15 @@ +fun foo() { + for (i in 1..10) { + val x = take() + if (x == null) { + do { + if (g()) break + } while (f()) + } + x.hashCode() + } +} + +fun take(): Any? = null +fun f(): Boolean{} +fun g(): Boolean{} \ No newline at end of file diff --git a/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.dump b/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.dump new file mode 100644 index 00000000000..7fea88635b5 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.dump @@ -0,0 +1,3 @@ +Resolve target: val x: kotlin.Any? +Skipped statements: +if (x == null) { for (s in c) { print(s) return } } diff --git a/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.kt b/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.kt new file mode 100644 index 00000000000..94d0e146c8a --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.kt @@ -0,0 +1,14 @@ +fun foo(c: Collection) { + for (i in 1..10) { + val x = take() + if (x == null) { + for (s in c) { + print(s) + return + } + } + x.hashCode() + } +} + +fun take(): Any? = null diff --git a/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.dump b/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.dump new file mode 100644 index 00000000000..75cc53db0b1 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.dump @@ -0,0 +1,3 @@ +Resolve target: val x: kotlin.Any? +Skipped statements: +if (x == null) { while (true) { if (g()) break } } diff --git a/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.kt b/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.kt new file mode 100644 index 00000000000..c211e0ae271 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.kt @@ -0,0 +1,15 @@ +fun foo() { + for (i in 1..10) { + val x = take() + if (x == null) { + while (true) { + if (g()) break + } + } + x.hashCode() + } +} + +fun take(): Any? = null +fun f(): Boolean{} +fun g(): Boolean{} \ No newline at end of file diff --git a/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.dump b/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.dump new file mode 100644 index 00000000000..53f9f180604 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.dump @@ -0,0 +1,3 @@ +Resolve target: val x: kotlin.Any? +Skipped statements: +if (x == null) { while (f()) { print(1) return } } diff --git a/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.kt b/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.kt new file mode 100644 index 00000000000..42f59c4d165 --- /dev/null +++ b/idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.kt @@ -0,0 +1,15 @@ +fun foo() { + for (i in 1..10) { + val x = take() + if (x == null) { + while (f()) { + print(1) + return + } + } + x.hashCode() + } +} + +fun take(): Any? = null +fun f(): Boolean{} diff --git a/idea/tests/org/jetbrains/jet/resolve/PartialBodyResolveTestGenerated.java b/idea/tests/org/jetbrains/jet/resolve/PartialBodyResolveTestGenerated.java index 19a58e5380d..1980bda1ac1 100644 --- a/idea/tests/org/jetbrains/jet/resolve/PartialBodyResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/resolve/PartialBodyResolveTestGenerated.java @@ -132,6 +132,18 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT doTest(fileName); } + @TestMetadata("IfNullDoWhileWithBreak.kt") + public void testIfNullDoWhileWithBreak() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullDoWhileWithBreak.kt"); + doTest(fileName); + } + + @TestMetadata("IfNullForWithReturn.kt") + public void testIfNullForWithReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullForWithReturn.kt"); + doTest(fileName); + } + @TestMetadata("IfNullPrint.kt") public void testIfNullPrint() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullPrint.kt"); @@ -144,6 +156,18 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT doTest(fileName); } + @TestMetadata("IfNullWhileTrueWithBreak.kt") + public void testIfNullWhileTrueWithBreak() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullWhileTrueWithBreak.kt"); + doTest(fileName); + } + + @TestMetadata("IfNullWhileWithReturn.kt") + public void testIfNullWhileWithReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullWhileWithReturn.kt"); + doTest(fileName); + } + @TestMetadata("IfReturn.kt") public void testIfReturn() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfReturn.kt");