mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IG: Update "Throwable not thrown" inspection for switch expressions (IDEA-203703)
This commit is contained in:
+43
-33
@@ -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<PsiReference> 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;
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-33
@@ -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;
|
||||
|
||||
+23
@@ -106,4 +106,27 @@ class L {
|
||||
final RuntimeException exception = new RuntimeException();
|
||||
I i2 = () -> exception;
|
||||
}
|
||||
}
|
||||
class Main {
|
||||
Runnable r = () -> <warning descr="Runtime exception instance 'new RuntimeException()' is not thrown">new RuntimeException()</warning>;
|
||||
|
||||
Throwable switchExpression1(int i) {
|
||||
return switch(i) {
|
||||
default -> new Throwable();
|
||||
};
|
||||
}
|
||||
|
||||
Throwable switchExpression2(int i) {
|
||||
for (int j = 0; j < 10; j++, <warning descr="Throwable instance 'new Throwable()' is not thrown">new Throwable()</warning>) {}
|
||||
|
||||
return switch(i) {
|
||||
default -> {
|
||||
break new Throwable();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void x(I i) {
|
||||
assert i.get() != null;
|
||||
}
|
||||
}
|
||||
+8
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user