From 96a576963ab3bbd986baea7d1fbd9e692d5b080a Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Mon, 25 Jul 2016 19:19:04 +0300 Subject: [PATCH] Java control flow: Fixed false positive for unreachable code in multi-catch clause (IDEA-138978) --- .../psi/controlFlow/ControlFlowAnalyzer.java | 16 +++++++++++++- .../advHighlighting7/IDEA138978.java | 22 +++++++++++++++++++ .../daemon/LightAdvHighlightingJdk7Test.java | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/IDEA138978.java diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index af22f3afae9e..08620c518598 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -21,10 +21,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import gnu.trove.THashMap; import gnu.trove.TIntArrayList; @@ -971,7 +973,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { ProgressManager.checkCanceled(); PsiParameter parameter = myCatchParameters.get(i); PsiType catchType = parameter.getType(); - if (catchType.isAssignableFrom(throwType) || throwType.isAssignableFrom(catchType)) { + if (catchType.isAssignableFrom(throwType) || mightBeAssignableFromSubclass(throwType, catchType)) { blocks.add(myCatchBlocks.get(i)); } } @@ -982,6 +984,18 @@ class ControlFlowAnalyzer extends JavaElementVisitor { return blocks; } + private static boolean mightBeAssignableFromSubclass(@NotNull final PsiClassType throwType, @NotNull PsiType catchType) { + if (catchType instanceof PsiDisjunctionType) { + return ContainerUtil.exists(((PsiDisjunctionType)catchType).getDisjunctions(), new Condition() { + @Override + public boolean value(PsiType catchDisjunction) { + return throwType.isAssignableFrom(catchDisjunction); + } + }); + } + return throwType.isAssignableFrom(catchType); + } + @Override public void visitAssertStatement(PsiAssertStatement statement) { startElement(statement); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/IDEA138978.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/IDEA138978.java new file mode 100644 index 000000000000..fa33861cdbe2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/IDEA138978.java @@ -0,0 +1,22 @@ +class MultiCatch { + + public String get(boolean b) { + try { + return b ? get1() : get2(); + } catch (EE1 | EE2 e) { + return null; // is reachable + } catch (E1 | E2 e) { + // + } + return null; + } + + String get1() throws E1 { return "1"; } + String get2() throws E2 { return "2"; } + + static class E extends Exception { } + static class E1 extends E { } + static class E2 extends E { } + static class EE1 extends E1 { } + static class EE2 extends E2 { } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index def1ddf09142..1658752c857c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -180,6 +180,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { public void testInaccessibleInferredTypeForVarargsArgument() { doTest(false, false);} public void testRuntimeClassCast() { doTest(true, false);} public void testTryWithResourcesWithMultipleCloseInterfaces() { doTest(false, false);} + public void testIDEA138978() { doTest(false, false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));