Partial body resolve: more efficient handling of loops

This commit is contained in:
Valentin Kipyatkov
2014-11-18 15:39:38 +03:00
parent 806bf3b942
commit 0a7d73ef6b
10 changed files with 128 additions and 3 deletions
@@ -212,6 +212,8 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J
private fun collectAlwaysExitPoints(expression: JetExpression?): Collection<JetExpression> {
val result = ArrayList<JetExpression>()
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
@@ -0,0 +1,3 @@
Resolve target: val x: kotlin.Any?
Skipped statements:
if (x == null) { do { if (g()) break } while (f()) }
@@ -0,0 +1,15 @@
fun foo() {
for (i in 1..10) {
val x = take()
if (x == null) {
do {
if (g()) break
} while (f())
}
<caret>x.hashCode()
}
}
fun take(): Any? = null
fun f(): Boolean{}
fun g(): Boolean{}
@@ -0,0 +1,3 @@
Resolve target: val x: kotlin.Any?
Skipped statements:
if (x == null) { for (s in c) { print(s) return } }
@@ -0,0 +1,14 @@
fun foo(c: Collection<String>) {
for (i in 1..10) {
val x = take()
if (x == null) {
for (s in c) {
print(s)
return
}
}
<caret>x.hashCode()
}
}
fun take(): Any? = null
@@ -0,0 +1,3 @@
Resolve target: val x: kotlin.Any?
Skipped statements:
if (x == null) { while (true) { if (g()) break } }
@@ -0,0 +1,15 @@
fun foo() {
for (i in 1..10) {
val x = take()
if (x == null) {
while (true) {
if (g()) break
}
}
<caret>x.hashCode()
}
}
fun take(): Any? = null
fun f(): Boolean{}
fun g(): Boolean{}
@@ -0,0 +1,3 @@
Resolve target: val x: kotlin.Any?
Skipped statements:
if (x == null) { while (f()) { print(1) return } }
@@ -0,0 +1,15 @@
fun foo() {
for (i in 1..10) {
val x = take()
if (x == null) {
while (f()) {
print(1)
return
}
}
<caret>x.hashCode()
}
}
fun take(): Any? = null
fun f(): Boolean{}
@@ -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");