diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java index 77b39c52c926..7917a8ef73d9 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -319,6 +319,15 @@ public class ControlFlowUtils { } public static boolean isInFinallyBlock(@NotNull PsiElement element) { + final PsiType type; + if (element instanceof PsiThrowStatement) { + final PsiThrowStatement throwStatement = (PsiThrowStatement)element; + final PsiExpression exception = throwStatement.getException(); + type = exception != null ? exception.getType() : null; + } + else { + type = null; + } PsiElement currentElement = element; while (true) { final PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(currentElement, PsiTryStatement.class, true, PsiClass.class, PsiLambdaExpression.class); @@ -326,17 +335,24 @@ public class ControlFlowUtils { return false; } final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); - if (finallyBlock != null) { - if (PsiTreeUtil.isAncestor(finallyBlock, currentElement, true)) { - final PsiMethod elementMethod = PsiTreeUtil.getParentOfType(currentElement, PsiMethod.class); - final PsiMethod finallyMethod = PsiTreeUtil.getParentOfType(finallyBlock, PsiMethod.class); - return elementMethod != null && elementMethod.equals(finallyMethod); - } + if (PsiTreeUtil.isAncestor(finallyBlock, currentElement, true)) { + return true; + } + if (type != null && isCaught(tryStatement, type)) { + return false; } currentElement = tryStatement; } } + public static boolean isCaught(PsiTryStatement tryStatement, PsiType exceptionType) { + for (PsiParameter parameter : tryStatement.getCatchBlockParameters()) { + final PsiType type = parameter.getType(); + if (type.isAssignableFrom(exceptionType)) return true; + } + return false; + } + public static boolean isInCatchBlock(@NotNull PsiElement element) { return PsiTreeUtil.getParentOfType(element, PsiCatchSection.class, true, PsiClass.class) != null; } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/throw_from_finally_block/ThrowFromFinallyBlock.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/throw_from_finally_block/ThrowFromFinallyBlock.java new file mode 100644 index 000000000000..dd65e08f00ee --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/throw_from_finally_block/ThrowFromFinallyBlock.java @@ -0,0 +1,51 @@ +package com.siyeh.igtest.errorhandling.throw_from_finally_block; + +import java.io.FileInputStream; +import java.io.IOException; + +public class ThrowFromFinallyBlock +{ + public void foo() throws Exception + { + try + { + return; + } + finally + { + throw new Exception(); + } + } + + public void bar() throws Exception + { + try + { + return; + } + finally + { + try + { + throw new Exception(); + } + finally + { + throw new Exception(); + } + } + } + + public void safe() throws IOException { + try (FileInputStream in = new FileInputStream("name")) { + + } catch (RuntimeException e) { + // ... + } finally { + try { + throw new NullPointerException(); + } catch (RuntimeException e) {} + } + } + +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/exceptionHandling/ThrowFromFinallyBlockInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/exceptionHandling/ThrowFromFinallyBlockInspection.java deleted file mode 100644 index d006df6f1b55..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/exceptionHandling/ThrowFromFinallyBlockInspection.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.siyeh.igtest.exceptionHandling; - -public class ThrowFromFinallyBlockInspection -{ - public void foo() throws Exception - { - try - { - return; - } - finally - { - throw new Exception(); - } - } - - public void bar() throws Exception - { - try - { - return; - } - finally - { - try - { - throw new Exception(); - } - finally - { - throw new Exception(); - } - } - } - -} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/ThrowFromFinallyBlockInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/ThrowFromFinallyBlockInspectionTest.java new file mode 100644 index 000000000000..d2a060f3d86e --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/ThrowFromFinallyBlockInspectionTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * (c) 2015 Silent Forest AB + * created: 07 April 2015 + */ +package com.siyeh.ig.errorhandling; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class ThrowFromFinallyBlockInspectionTest extends LightInspectionTestCase { + + public void testThrowFromFinallyBlock() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new ThrowFromFinallyBlockInspection(); + } +}