From f25a27d0436d1fe24352416b6512e91fd0db643b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Nov 2012 15:47:08 +0100 Subject: [PATCH] Fix dataflow for unchecked exceptions in multi-catch --- .../dataFlow/ControlFlowAnalyzer.java | 48 +++++++++++-------- .../fixture/CatchRuntimeException.java | 26 +++++++++- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index df5f8a45394b..0e540eaa944f 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -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--) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CatchRuntimeException.java b/java/java-tests/testData/inspection/dataFlow/fixture/CatchRuntimeException.java index 1967eb4478ae..193b3bcf81c4 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/CatchRuntimeException.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CatchRuntimeException.java @@ -3,8 +3,8 @@ import org.jetbrains.annotations.NotNull; public class BrokenAlignment { @NotNull - Object test(){ - try{ + Object test1() { + try { bar(null); return null; } @@ -13,6 +13,28 @@ public class BrokenAlignment { } } + @NotNull + Object test2() { + try { + bar(null); + return null; + } + catch (IllegalArgumentException | IllegalStateException e) { + return null; + } + } + + @NotNull + Object test3() { + try { + bar(null); + return null; + } + catch (AssertionError | IllegalStateException e) { + return null; + } + } + public void bar(@NotNull Object foo) { assert foo != null; }