Partial body resolve: more efficient handling of loops
This commit is contained in:
+33
-3
@@ -212,6 +212,8 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J
|
|||||||
private fun collectAlwaysExitPoints(expression: JetExpression?): Collection<JetExpression> {
|
private fun collectAlwaysExitPoints(expression: JetExpression?): Collection<JetExpression> {
|
||||||
val result = ArrayList<JetExpression>()
|
val result = ArrayList<JetExpression>()
|
||||||
expression?.accept(object : ControlFlowVisitor() {
|
expression?.accept(object : ControlFlowVisitor() {
|
||||||
|
var insideLoop = false
|
||||||
|
|
||||||
override fun visitReturnExpression(expression: JetReturnExpression) {
|
override fun visitReturnExpression(expression: JetReturnExpression) {
|
||||||
result.add(expression)
|
result.add(expression)
|
||||||
}
|
}
|
||||||
@@ -220,13 +222,41 @@ class PartialBodyResolveFilter(elementToResolve: JetElement, private val body: J
|
|||||||
result.add(expression)
|
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) {
|
override fun visitBreakExpression(expression: JetBreakExpression) {
|
||||||
result.add(expression)
|
if (!insideLoop || expression.getLabelName() != null) {
|
||||||
|
result.add(expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContinueExpression(expression: JetContinueExpression) {
|
override fun visitContinueExpression(expression: JetContinueExpression) {
|
||||||
result.add(expression)
|
if (!insideLoop || expression.getLabelName() != null) {
|
||||||
|
result.add(expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result
|
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);
|
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")
|
@TestMetadata("IfNullPrint.kt")
|
||||||
public void testIfNullPrint() throws Exception {
|
public void testIfNullPrint() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullPrint.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfNullPrint.kt");
|
||||||
@@ -144,6 +156,18 @@ public class PartialBodyResolveTestGenerated extends AbstractPartialBodyResolveT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("IfReturn.kt")
|
||||||
public void testIfReturn() throws Exception {
|
public void testIfReturn() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfReturn.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/resolve/partialBodyResolve/IfReturn.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user