diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableNotThrownInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableNotThrownInspection.java index 2eb166f19a2c..a7e21d5b6800 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableNotThrownInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableNotThrownInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2017 Bas Leijdekkers + * Copyright 2008-2018 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NotNull; @@ -121,10 +122,8 @@ public class ThrowableNotThrownInspection extends BaseInspection { return isIgnored(expression, true); } - private static boolean isIgnored(PsiElement element, boolean checkDeep) { - final PsiElement parent = - PsiTreeUtil.getParentOfType(element, PsiStatement.class, PsiExpressionList.class, PsiVariable.class, - PsiLambdaExpression.class, PsiPolyadicExpression.class, PsiInstanceOfExpression.class); + private static boolean isIgnored(PsiExpression expression, boolean checkDeep) { + final PsiElement parent = getHandlingParent(expression); if (parent instanceof PsiVariable) { if (!(parent instanceof PsiLocalVariable)) { return false; @@ -133,45 +132,56 @@ public class ThrowableNotThrownInspection extends BaseInspection { return checkDeep && !isUsedElsewhere((PsiLocalVariable)parent); } } - if (!(parent instanceof PsiStatement)) { - return false; - } - if (parent instanceof PsiReturnStatement || parent instanceof PsiThrowStatement || parent instanceof PsiForeachStatement) { - return false; - } - if (parent instanceof PsiExpressionStatement) { + else if (parent instanceof PsiExpressionStatement) { + // void method (like printStackTrace()) provides no result, thus can't be ignored final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)parent; final PsiExpression expression1 = expressionStatement.getExpression(); - if (expression1 instanceof PsiMethodCallExpression) { - // void method (like printStackTrace()) provides no result, thus is not ignored - return !PsiType.VOID.equals(expression1.getType()); + return !PsiType.VOID.equals(expression1.getType()); + } + else if (parent instanceof PsiExpressionList) { + return parent.getParent() instanceof PsiExpressionListStatement; + } + else if (parent instanceof PsiLambdaExpression) { + return PsiType.VOID.equals(LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)parent)); + } + else if (parent instanceof PsiReturnStatement || parent instanceof PsiThrowStatement || parent instanceof PsiLoopStatement + || parent instanceof PsiIfStatement || parent instanceof PsiAssertStatement) { + return false; + } + else if (parent instanceof PsiAssignmentExpression) { + final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent; + final PsiExpression rhs = assignmentExpression.getRExpression(); + if (!PsiTreeUtil.isAncestor(rhs, expression, false)) { + return false; } - else if (expression1 instanceof PsiAssignmentExpression) { - final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression1; - final PsiExpression rhs = assignmentExpression.getRExpression(); - if (!PsiTreeUtil.isAncestor(rhs, element, false)) { - return false; - } - final PsiExpression lhs = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression()); - if (!(lhs instanceof PsiReferenceExpression)) { - return false; - } - final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs; - final PsiElement target = referenceExpression.resolve(); - if (!(target instanceof PsiLocalVariable)) { - return false; - } - return checkDeep && !isUsedElsewhere((PsiLocalVariable)target); + final PsiExpression lhs = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression()); + if (!(lhs instanceof PsiReferenceExpression)) { + return false; } + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs; + final PsiElement target = referenceExpression.resolve(); + if (!(target instanceof PsiLocalVariable)) { + return false; + } + return checkDeep && !isUsedElsewhere((PsiLocalVariable)target); } return true; } + private static PsiElement getHandlingParent(PsiExpression expression) { + while (true) { + final PsiElement parent = ExpressionUtils.getPassThroughParent(expression); + if (!(parent instanceof PsiExpression) || parent instanceof PsiLambdaExpression || parent instanceof PsiAssignmentExpression) { + return parent; + } + expression = (PsiExpression)parent; + } + } + private static boolean isUsedElsewhere(PsiLocalVariable variable) { final Query query = ReferencesSearch.search(variable); for (PsiReference reference : query) { - final PsiElement usage = reference.getElement(); - if (!isIgnored(usage, false)) { + if (reference instanceof PsiReferenceExpression && !isIgnored((PsiExpression)reference, false)) { return true; } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java index 18b6b48a475e..91914c17795e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpressionUtils.java @@ -1420,4 +1420,36 @@ public class ExpressionUtils { } } } + + public static PsiElement getPassThroughParent(PsiExpression expression) { + while (true) { + final PsiElement parent = expression.getParent(); + if (parent instanceof PsiParenthesizedExpression || parent instanceof PsiTypeCastExpression) { + expression = (PsiExpression)parent; + continue; + } + else if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression)parent).getCondition() != expression) { + expression = (PsiExpression)parent; + continue; + } + else if (parent instanceof PsiExpressionStatement) { + final PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiSwitchLabeledRuleStatement) { + final PsiSwitchBlock block = ((PsiSwitchLabeledRuleStatement)grandParent).getEnclosingSwitchBlock(); + if (block instanceof PsiSwitchExpression) { + expression = (PsiExpression)block; + continue; + } + } + } + else if (parent instanceof PsiBreakStatement) { + final PsiElement exitedElement = ((PsiBreakStatement)parent).findExitedElement(); + if (exitedElement instanceof PsiSwitchExpression) { + expression = (PsiExpression)exitedElement; + continue; + } + } + return parent; + } + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java index 8ff6ca98b53c..d5df5b30236e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/resources/ResourceInspection.java @@ -322,7 +322,7 @@ public abstract class ResourceInspection extends BaseInspection { } } } - final PsiElement parent = getPassthroughParent(resourceCreationExpression); + final PsiElement parent = ExpressionUtils.getPassThroughParent(resourceCreationExpression); if (parent instanceof PsiReturnStatement) { return true; } @@ -361,38 +361,6 @@ public abstract class ResourceInspection extends BaseInspection { return visitor.isEscaped(); } - private static PsiElement getPassthroughParent(PsiExpression expression) { - while (true) { - final PsiElement parent = expression.getParent(); - if (parent instanceof PsiParenthesizedExpression || parent instanceof PsiTypeCastExpression) { - expression = (PsiExpression)parent; - continue; - } - else if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression)parent).getCondition() != expression) { - expression = (PsiExpression)parent; - continue; - } - else if (parent instanceof PsiExpressionStatement) { - final PsiElement grandParent = parent.getParent(); - if (grandParent instanceof PsiSwitchLabeledRuleStatement) { - final PsiSwitchBlock block = ((PsiSwitchLabeledRuleStatement)grandParent).getEnclosingSwitchBlock(); - if (block instanceof PsiSwitchExpression) { - expression = (PsiExpression)block; - continue; - } - } - } - else if (parent instanceof PsiBreakStatement) { - final PsiElement exitedElement = ((PsiBreakStatement)parent).findExitedElement(); - if (exitedElement instanceof PsiSwitchExpression) { - expression = (PsiExpression)exitedElement; - continue; - } - } - return parent; - } - } - private class CloseVisitor extends JavaRecursiveElementWalkingVisitor { private boolean containsClose; private final PsiVariable resource; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/throwable_instance_never_thrown/ThrowableInstanceNeverThrown.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/throwable_instance_never_thrown/ThrowableInstanceNeverThrown.java index d4374670bce9..36e046223152 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/throwable_instance_never_thrown/ThrowableInstanceNeverThrown.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/throwable_instance_never_thrown/ThrowableInstanceNeverThrown.java @@ -106,4 +106,27 @@ class L { final RuntimeException exception = new RuntimeException(); I i2 = () -> exception; } +} +class Main { + Runnable r = () -> new RuntimeException(); + + Throwable switchExpression1(int i) { + return switch(i) { + default -> new Throwable(); + }; + } + + Throwable switchExpression2(int i) { + for (int j = 0; j < 10; j++, new Throwable()) {} + + return switch(i) { + default -> { + break new Throwable(); + } + }; + } + + void x(I i) { + assert i.get() != null; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ThrowableInstanceNeverThrownInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ThrowableInstanceNeverThrownInspectionTest.java index 74657b670527..cfcee1f00be9 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ThrowableInstanceNeverThrownInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ThrowableInstanceNeverThrownInspectionTest.java @@ -1,7 +1,9 @@ package com.siyeh.ig.bugs; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ThrowableInstanceNeverThrownInspectionTest extends LightInspectionTestCase { @@ -16,6 +18,12 @@ public class ThrowableInstanceNeverThrownInspectionTest extends LightInspectionT return new ThrowableNotThrownInspection(); } + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_12; + } + @Override protected String getBasePath() { return "/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/throwable_instance_never_thrown";