IDEA-52624 Returns from endless loops are not considered 'all execution paths' returning a value

This commit is contained in:
peter
2010-03-09 12:54:15 +00:00
parent eed9138dbd
commit ba2bc480c6
10 changed files with 42 additions and 8 deletions
@@ -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<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);
@@ -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;
@@ -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;
@@ -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());
@@ -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());
}
+1 -1
View 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
+1 -1
View 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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
def foo() {
while (true) {
return 239
}
}