diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 3eff8f0b667b..0702fc30acdb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -15,8 +15,10 @@ */ package org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiConstantEvaluationHelper; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.psi.tree.IElementType; @@ -51,6 +53,12 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { private List myInstructions; private Stack myProcessingStack; + private PsiConstantEvaluationHelper myConstantEvaluator; + + public ControlFlowBuilder(Project project) { + myConstantEvaluator = JavaPsiFacade.getInstance(project).getConstantEvaluationHelper(); + + } private class ExceptionInfo { GrCatchClause myClause; @@ -485,7 +493,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (condition != null) { condition.accept(this); } - addPendingEdge(whileStatement, myHead); //break + final boolean endless = Boolean.TRUE.equals(myConstantEvaluator.computeConstantExpression(condition)); + if (!endless) { + addPendingEdge(whileStatement, myHead); //break + } final GrCondition body = whileStatement.getBody(); if (body != null) { body.accept(this); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java index 2e2246893e74..1577d8611e01 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java @@ -177,7 +177,7 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi public Instruction[] getControlFlow() { if (myControlFlow == null) { - myControlFlow = new ControlFlowBuilder().buildControlFlow(this, null, null); + myControlFlow = new ControlFlowBuilder(getProject()).buildControlFlow(this, null, null); } return myControlFlow; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index 921542e897b0..e35d332bdab7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -49,7 +49,7 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode public Instruction[] getControlFlow() { if (myControlFlow == null) { - myControlFlow = new ControlFlowBuilder().buildControlFlow(this, null, null); + myControlFlow = new ControlFlowBuilder(getProject()).buildControlFlow(this, null, null); } return myControlFlow; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java index 62e41e0863e9..6d0696852f6b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java @@ -33,6 +33,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase { public void testMissingReturnOvertReturnType() throws Throwable {doTest();} public void testMissingReturnFromClosure() throws Throwable {doTest();} public void testReturnsWithoutValue() throws Throwable {doTest();} + public void testEndlessLoop() throws Throwable {doTest();} private void doTest() throws Exception { myFixture.enableInspections(new MissingReturnInspection()); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java index f4f314a4884d..0454648a1d18 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java @@ -44,6 +44,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { public void testTry7() throws Throwable { doTest(); } public void testWhile1() throws Throwable { doTest(); } public void testWhile2() throws Throwable { doTest(); } + public void testWhileNonConstant() throws Throwable { doTest(); } public void testIfInstanceofElse() throws Throwable { doTest(); } private static String dumpControlFlow(Instruction[] instructions) { @@ -66,7 +67,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { final PsiElement start = file.findElementAt(model.hasSelection() ? model.getSelectionStart() : 0); final PsiElement end = file.findElementAt(model.hasSelection() ? model.getSelectionEnd() - 1 : file.getTextLength() - 1); final GrControlFlowOwner owner = PsiTreeUtil.getParentOfType(PsiTreeUtil.findCommonParent(start, end), GrControlFlowOwner.class, false); - final Instruction[] instructions = new ControlFlowBuilder().buildControlFlow(owner, null, null); + final Instruction[] instructions = new ControlFlowBuilder(getProject()).buildControlFlow(owner, null, null); final String cf = dumpControlFlow(instructions); assertEquals(input.get(1).trim(), cf.trim()); } diff --git a/plugins/groovy/testdata/groovy/controlFlow/while1.test b/plugins/groovy/testdata/groovy/controlFlow/while1.test index 323c64ef13eb..f0cd07908070 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/while1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/while1.test @@ -6,7 +6,7 @@ while (true) { ----- 0(1) element: null 1(2) WRITE i -2(3,7) element: WHILE statement +2(3) element: WHILE statement 3(4,5) element: IF statement 4(7) READ i 5(6) READ i diff --git a/plugins/groovy/testdata/groovy/controlFlow/while2.test b/plugins/groovy/testdata/groovy/controlFlow/while2.test index 4464fd5ef1b7..e3542ab03ed1 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/while2.test +++ b/plugins/groovy/testdata/groovy/controlFlow/while2.test @@ -6,7 +6,7 @@ while (true) { ----- 0(1) element: null 1(2) WRITE i -2(3,7) element: WHILE statement +2(3) element: WHILE statement 3(4,5) element: IF statement 4(2) READ i 5(6) READ i diff --git a/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test new file mode 100644 index 000000000000..3f126683e0eb --- /dev/null +++ b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test @@ -0,0 +1,15 @@ +i = 0 +while (condition()) { + if (i > 10) break + i++ +} +----- +0(1) element: null +1(2) WRITE i +2(3) element: WHILE statement +3(4,8) READ condition +4(5,6) element: IF statement +5(8) READ i +6(7) READ i +7(2) WRITE i +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test index 2732a393f9d1..e079d4bdc59d 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test @@ -12,9 +12,10 @@ def i = 6 println i ----- def i = 6 -i = testMethod(i) +i = testMethod() -private int testMethod(int i) { +private int testMethod() { + int i while (true) { println "preved" i = 42 diff --git a/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy b/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy new file mode 100644 index 000000000000..7e19ff80273f --- /dev/null +++ b/plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy @@ -0,0 +1,5 @@ +def foo() { + while (true) { + return 239 + } +} \ No newline at end of file