Fix dataflow for unchecked exceptions in multi-catch

This commit is contained in:
Roman Shevchenko
2012-11-21 15:47:25 +01:00
parent fd09e4393d
commit f25a27d043
2 changed files with 51 additions and 23 deletions
@@ -34,10 +34,7 @@ import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
class ControlFlowAnalyzer extends JavaElementVisitor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer");
@@ -639,28 +636,37 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
for (int i = myCatchStack.size() - 1; i >= 0; i--) {
CatchDescriptor cd = myCatchStack.get(i);
if (cd.isFinally()) {
pushUnknown();
final ConditionalGotoInstruction branch = new ConditionalGotoInstruction(-1, false, null);
addInstruction(branch);
addInstruction(new EmptyStackInstruction());
addInstruction(new GosubInstruction(cd.getJumpOffset()));
addInstruction(new ReturnInstruction());
branch.setOffset(myCurrentFlow.getInstructionCount());
addConditionalRuntimeThrow(cd, false);
continue;
}
else if (cd.getType() instanceof PsiClassType &&
ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)cd.getType())) {
pushUnknown();
final ConditionalGotoInstruction branch = new ConditionalGotoInstruction(-1, false, null);
addInstruction(branch);
addInstruction(new EmptyStackInstruction());
addInstruction(new PushInstruction(myFactory.getNotNullFactory().create(myRuntimeException), null));
addGotoCatch(cd);
branch.setOffset(myCurrentFlow.getInstructionCount());
return;
PsiType type = cd.getType();
if (type instanceof PsiDisjunctionType) {
type = ((PsiDisjunctionType)type).getLeastUpperBound();
}
if (type instanceof PsiClassType && ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)type)) {
addConditionalRuntimeThrow(cd, true);
break;
}
}
}
private void addConditionalRuntimeThrow(CatchDescriptor cd, boolean forCatch) {
pushUnknown();
final ConditionalGotoInstruction branch = new ConditionalGotoInstruction(-1, false, null);
addInstruction(branch);
addInstruction(new EmptyStackInstruction());
if (forCatch) {
addInstruction(new PushInstruction(myFactory.getNotNullFactory().create(myRuntimeException), null));
addGotoCatch(cd);
}
else {
addInstruction(new GosubInstruction(cd.getJumpOffset()));
addInstruction(new ReturnInstruction());
}
branch.setOffset(myCurrentFlow.getInstructionCount());
}
private void addThrowCode(PsiType exceptionClass) {
if (exceptionClass == null) return;
for (int i = myCatchStack.size() - 1; i >= 0; i--) {
@@ -3,8 +3,8 @@ import org.jetbrains.annotations.NotNull;
public class BrokenAlignment {
@NotNull
Object test(){
try{
Object test1() {
try {
bar(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
}
@@ -13,6 +13,28 @@ public class BrokenAlignment {
}
}
@NotNull
Object test2() {
try {
bar(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
}
catch (IllegalArgumentException | IllegalStateException e) {
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
}
}
@NotNull
Object test3() {
try {
bar(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
}
catch (AssertionError | IllegalStateException e) {
return <warning descr="'null' is returned by the method declared as @NotNull">null</warning>;
}
}
public void bar(@NotNull Object foo) {
assert <warning descr="Condition 'foo != null' is always 'true'">foo != null</warning>;
}