IDEA-84488 control flow of try with some catches

This commit is contained in:
Maxim.Medvedev
2012-04-27 16:25:37 +04:00
parent 04d2198017
commit 73747f4706
8 changed files with 92 additions and 8 deletions
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.controlFlow;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrFinallyClause;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.InstructionImpl;
import java.util.ArrayDeque;
@@ -25,8 +26,8 @@ import java.util.Deque;
* @author peter
*/
public class ReturnInstruction extends InstructionImpl {
public ReturnInstruction(int num) {
super(null, num);
public ReturnInstruction(GrFinallyClause finallyClause, int num) {
super(finallyClause, num);
}
public String toString() {
@@ -430,9 +430,8 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
if (ControlFlowUtils.isIncOrDecOperand(refExpr) && !myAssertionsOnly) {
final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, READ);
addNode(i);
addNodeAndCheckPending(i);
addNode(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, WRITE));
checkPending(i);
}
else {
boolean isWrite = !myAssertionsOnly && PsiUtil.isLValue(refExpr);
@@ -818,25 +817,32 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
}
}
//save added postcalls into separate list because we don't want returnInstruction grabbed their pending edges
List<Pair<InstructionImpl, GroovyPsiElement>> pendingPostCalls = myPending;
myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
myHead = finallyInstruction;
finallyClause.accept(this);
final ReturnInstruction returnInstruction = new ReturnInstruction(myInstructionNumber++);
final ReturnInstruction returnInstruction = new ReturnInstruction(finallyClause, myInstructionNumber++);
for (AfterCallInstruction postCall : postCalls) {
postCall.setReturnInstruction(returnInstruction);
addEdge(returnInstruction, postCall);
}
addNode(returnInstruction);
addNodeAndCheckPending(returnInstruction);
interruptFlow();
finishNode(finallyInstruction);
assert oldPending != null;
oldPending.addAll(myPending);
oldPending.addAll(pendingPostCalls);
myPending = oldPending;
}
else {
if (tryEnd != null) {
addPendingEdge(tryCatchStatement, tryEnd);
}
for (InstructionImpl catchEnd : catches) {
addPendingEdge(tryBlock, catchEnd);
}
}
}
@@ -432,6 +432,10 @@ class A {
doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection())
}
public void testUsedInCatch() {
doTest(new UnusedDefInspection())
}
public void testStringAssignableToChar() {
doTest(new GroovyAssignabilityCheckInspection());
}
@@ -49,6 +49,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase {
public void testTry7() throws Throwable { doTest(); }
public void testTry8() throws Throwable { doTest(); }
public void testTry9() throws Throwable { doTest(); }
public void testTry10() throws Throwable { doTest(); }
public void testWhile1() throws Throwable { doTest(); }
public void testWhile2() throws Throwable { doTest(); }
public void testWhileNonConstant() throws Throwable { doTest(); }
@@ -57,6 +58,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase {
public void testSwitchInTryWithThrows() {doTest();}
public void testClosure() {doTest();}
public void testAnonymous() {doTest();}
public void testSomeCatches() {doTest();}
public void doTest() {
final List<String> input = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test");
@@ -0,0 +1,34 @@
String s = '';
try {
print 2
}
catch (UnsupportedOperationException ignored) {
s=''
}
catch (RuntimeException ignored) {
s = ''
}
catch (Exception ignored) {
s = ''
}
print s
-----
0(1) element: null
1(2) WRITE s
2(3) element: Open block
3(4) READ print
4(5,8,11,14) THROW. element: Call expression
5(6) element: Catch clause
6(7) WRITE ignored
7(14) WRITE s
8(9) element: Catch clause
9(10) WRITE ignored
10(14) WRITE s
11(12) element: Catch clause
12(13) WRITE ignored
13(14) WRITE s
14(15) READ print
15(16) READ s
16(17) ARGUMENT element: Reference expression
17(18) element: Call expression MAYBE_RETURN
18() element: null
+22
View File
@@ -0,0 +1,22 @@
try {}
finally {
for (;;){
if (abc) break
}
}
cde
-----
0(1) element: null
1(3) element: Open block
2(5) element: Finally clause
3(2,4) CALL 2
4(11) AFTER CALL 3
5(6) element: For statement
6(7) element: Block statement
7(8,9) element: IF statement
8(10) READ abc
9(5) element: IF statement
10(4) RETURN
11(12) READ cde
12(13) element: Reference expression MAYBE_RETURN
13() element: null
+1 -1
View File
@@ -21,7 +21,7 @@ finally {
6(13) AFTER CALL 5
7(8) element: Open block
8(9) READ i
9(10,13) THROW. element: Method call
9(10,12) THROW. element: Method call
10(11) element: Catch clause
11(12) WRITE ignored
12(6) RETURN
+15
View File
@@ -0,0 +1,15 @@
String s = '';
try {
print 2
}
catch (UnsupportedOperationException ignored) {
<warning descr="Assignment is not used">s</warning>=''
s=''
}
catch (RuntimeException ignored) {
s = ''
}
catch (Exception ignored) {
s = ''
}
print s