IDEA-52624 Returns from endless loops are not considered 'all execution paths' return...
authorpeter <peter.gromov@jetbrains.com>
Tue, 9 Mar 2010 12:41:56 +0000 (12:41 +0000)
committerpeter <peter.gromov@jetbrains.com>
Tue, 9 Mar 2010 12:54:15 +0000 (12:54 +0000)
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java
plugins/groovy/testdata/groovy/controlFlow/while1.test
plugins/groovy/testdata/groovy/controlFlow/while2.test
plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test [new file with mode: 0644]
plugins/groovy/testdata/groovy/refactoring/extractMethod/inter1.test
plugins/groovy/testdata/highlighting/missingReturn/EndlessLoop.groovy [new file with mode: 0644]

index 3eff8f0b667b2cc2533170c34f160e659948d9d7..0702fc30acdb1261f9f8e92bdd45d162e48cf205 100644 (file)
  */
 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<InstructionImpl> myInstructions;
 
   private Stack<InstructionImpl> 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);
index 2e2246893e74bb2204cdbd177f047d452f6b0c5f..1577d8611e015b52445d56e1e021c207deec2dd3 100644 (file)
@@ -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;
index 921542e897b01b3fe4ff9ecb6431258fde9e5a20..e35d332bdab7341e49c20ce2378244815681811d 100644 (file)
@@ -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;
index 62e41e0863e96836299dacdfd9e39b7140e62531..6d0696852f6bddd3723a0f7ab070831be9f69484 100644 (file)
@@ -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());
index f4f314a4884d5d7167876ce7741a776870def2ed..0454648a1d1860e79a2ffef9e40c6701c3e807e3 100644 (file)
@@ -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());
   }
index 323c64ef13eb3377c03742fa21464e063b4f6e89..f0cd07908070a379668ef3143f5410821375f821 100644 (file)
@@ -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
index 4464fd5ef1b710aaba8a67d642b666cfafa4e7b8..e3542ab03ed1b6fd31b661d962e35287f6bc046c 100644 (file)
@@ -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 (file)
index 0000000..3f12668
--- /dev/null
@@ -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
index 2732a393f9d10d830a1499b05b888c1ed224d0a6..e079d4bdc59d875158cee0ad2cf78198addacce5 100644 (file)
@@ -12,9 +12,10 @@ def i = 6
 println i
 -----
 def i = 6
-i = <caret>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 (file)
index 0000000..7e19ff8
--- /dev/null
@@ -0,0 +1,5 @@
+def foo() {
+  while (true) {
+    return 239
+  }
+}
\ No newline at end of file