mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java redundant cast: cleanup: visitor finally inverted
GitOrigin-RevId: 8b4449e6d9163c24b046aad9065e5ec055d6d62c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
78891be4bb
commit
1bc4cda08e
@@ -34,11 +34,11 @@ public class RedundantCastUtil {
|
||||
@NotNull
|
||||
public static List<PsiTypeCastExpression> getRedundantCastsInside(@NotNull PsiElement where) {
|
||||
MyCollectingVisitor visitor = new MyCollectingVisitor();
|
||||
if (where instanceof PsiField) {
|
||||
where.accept(visitor);
|
||||
if (where instanceof PsiClass) {
|
||||
where.acceptChildren(visitor);
|
||||
}
|
||||
else {
|
||||
where.acceptChildren(visitor);
|
||||
where.accept(visitor);
|
||||
}
|
||||
return new ArrayList<>(visitor.myFoundCasts);
|
||||
}
|
||||
@@ -69,11 +69,6 @@ public class RedundantCastUtil {
|
||||
// avoid multiple visit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethod(PsiMethod method) {
|
||||
// avoid multiple visit
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerCast(@NotNull PsiTypeCastExpression typeCast) {
|
||||
myFoundCasts.add(typeCast);
|
||||
@@ -98,6 +93,16 @@ public class RedundantCastUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private void addIfNarrowing(PsiExpression expression, PsiType expectedTypeByParent) {
|
||||
expression = deparenthesizeExpression(expression);
|
||||
if (expression instanceof PsiTypeCastExpression) {
|
||||
PsiExpression operand = getInnerMostOperand(expression);
|
||||
if (operand != null) {
|
||||
addIfNarrowing((PsiTypeCastExpression)expression, operand.getType(), expectedTypeByParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerCast(@NotNull PsiTypeCastExpression typeCast) {
|
||||
foundRedundantCast = typeCast;
|
||||
stopWalking();
|
||||
@@ -385,27 +390,7 @@ public class RedundantCastUtil {
|
||||
!(newResult instanceof MethodCandidateInfo && ((MethodCandidateInfo)newResult).getInferenceErrorMessage() != null) &&
|
||||
newResult.getSubstitutor().equals(oldResult.getSubstitutor())) {
|
||||
PsiExpression newArg = PsiUtil.deparenthesizeExpression(newArgs[i]);
|
||||
if (newArg instanceof PsiConditionalExpression && PsiPolyExpressionUtil.isPolyExpression(newArg)) {
|
||||
PsiType targetType = newArg.getType();
|
||||
LOG.assertTrue(targetType != null);
|
||||
//target type is detected by method call
|
||||
//check that both sides are fine with that
|
||||
PsiExpression thenExpression = ((PsiConditionalExpression)newArg).getThenExpression();
|
||||
PsiType thenType = thenExpression != null ? thenExpression.getType() : null;
|
||||
PsiExpression elseExpression = ((PsiConditionalExpression)newArg).getElseExpression();
|
||||
PsiType elseType = elseExpression != null ? elseExpression.getType() : null;
|
||||
if (thenType != null && targetType.isAssignableFrom(thenType) &&
|
||||
elseType != null && targetType.isAssignableFrom(elseType)) {
|
||||
addToResults(cast);
|
||||
}
|
||||
else {
|
||||
newArg.replace(arg);
|
||||
}
|
||||
}
|
||||
else if (!(newArg instanceof PsiFunctionalExpression)) {
|
||||
addToResults(cast);
|
||||
}
|
||||
else {
|
||||
if (newArg instanceof PsiFunctionalExpression) {
|
||||
final boolean varargs = newResult instanceof MethodCandidateInfo && ((MethodCandidateInfo)newResult).isVarargs();
|
||||
final PsiType parameterType = PsiTypesUtil.getParameterType(parameters, i, varargs);
|
||||
PsiType newArgType = newResult.getSubstitutor().substitute(parameterType);
|
||||
@@ -421,6 +406,9 @@ public class RedundantCastUtil {
|
||||
newArg.replace(arg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addToResults(cast);
|
||||
}
|
||||
}
|
||||
else {
|
||||
newArgs[i].replace(arg);
|
||||
@@ -553,9 +541,6 @@ public class RedundantCastUtil {
|
||||
addToResults(innerCast);
|
||||
}
|
||||
}
|
||||
else {
|
||||
processAlreadyHasTypeCast(typeCast);
|
||||
}
|
||||
super.visitTypeCastExpression(typeCast);
|
||||
}
|
||||
|
||||
@@ -694,17 +679,23 @@ public class RedundantCastUtil {
|
||||
|
||||
@Override
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
visitSwitchBlock(statement);
|
||||
visitSwitchBlockSelector(statement);
|
||||
super.visitSwitchStatement(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSwitchExpression(PsiSwitchExpression expression) {
|
||||
visitSwitchBlock(expression);
|
||||
visitSwitchBlockSelector(expression);
|
||||
|
||||
PsiType expectedTypeByParent = PsiTypesUtil.getExpectedTypeByParent(expression);
|
||||
for (PsiExpression resultExpression : PsiUtil.getSwitchResultExpressions(expression)) {
|
||||
addIfNarrowing(resultExpression, expectedTypeByParent);
|
||||
}
|
||||
|
||||
super.visitSwitchExpression(expression);
|
||||
}
|
||||
|
||||
private void visitSwitchBlock(PsiSwitchBlock expression) {
|
||||
private void visitSwitchBlockSelector(PsiSwitchBlock expression) {
|
||||
PsiExpression switchVariable = deparenthesizeExpression(expression.getExpression());
|
||||
if (switchVariable instanceof PsiTypeCastExpression) {
|
||||
PsiExpression operand = ((PsiTypeCastExpression)switchVariable).getOperand();
|
||||
@@ -721,58 +712,84 @@ public class RedundantCastUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAssertStatement(PsiAssertStatement statement) {
|
||||
addIfNarrowing(statement.getAssertCondition(), PsiType.BOOLEAN);
|
||||
addIfNarrowing(statement.getAssertDescription(), PsiType.getJavaLangString(statement.getManager(), statement.getResolveScope()));
|
||||
super.visitAssertStatement(statement);
|
||||
}
|
||||
|
||||
|
||||
private void processAlreadyHasTypeCast(PsiTypeCastExpression typeCast){
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(typeCast.getParent());
|
||||
if (parent instanceof PsiExpressionList) return; // do not replace in arg lists - should be handled by parent
|
||||
if (parent instanceof PsiReturnStatement) return;
|
||||
if (parent instanceof PsiTypeCastExpression) return;
|
||||
if (parent instanceof PsiPolyadicExpression) return;
|
||||
if (parent instanceof PsiForeachStatement) return;
|
||||
if (parent instanceof PsiInstanceOfExpression) return;
|
||||
if (parent instanceof PsiThrowStatement) return;
|
||||
if (parent instanceof PsiSynchronizedStatement) return;
|
||||
if (parent instanceof PsiLambdaExpression) return;
|
||||
if (parent instanceof PsiSwitchBlock) return;
|
||||
if (parent instanceof PsiArrayAccessExpression) return;
|
||||
if (parent instanceof PsiReferenceExpression) return;
|
||||
if (parent instanceof PsiAssignmentExpression) return;
|
||||
if (parent instanceof PsiVariable) return;
|
||||
if (parent instanceof PsiArrayInitializerExpression) return;
|
||||
if (parent instanceof PsiConditionalExpression) return;
|
||||
@Override
|
||||
public void visitYieldStatement(PsiYieldStatement statement) {
|
||||
PsiSwitchExpression switchExpression = statement.findEnclosingExpression();
|
||||
PsiType expectedTypeByParent = switchExpression != null ? PsiTypesUtil.getExpectedTypeByParent(switchExpression) : null;
|
||||
addIfNarrowing(statement.getExpression(), expectedTypeByParent);
|
||||
super.visitYieldStatement(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
|
||||
addIfNarrowing(statement.getCondition(), PsiType.BOOLEAN);
|
||||
super.visitDoWhileStatement(statement);
|
||||
}
|
||||
|
||||
if (isTypeCastSemantic(typeCast)) return;
|
||||
@Override
|
||||
public void visitIfStatement(PsiIfStatement statement) {
|
||||
addIfNarrowing(statement.getCondition(), PsiType.BOOLEAN);
|
||||
super.visitIfStatement(statement);
|
||||
}
|
||||
|
||||
PsiTypeElement typeElement = typeCast.getCastType();
|
||||
if (typeElement == null) return;
|
||||
final PsiType castTo = typeElement.getType();
|
||||
final PsiExpression operand = deparenthesizeExpression(typeCast.getOperand());
|
||||
if (operand == null) return;
|
||||
@Override
|
||||
public void visitWhileStatement(PsiWhileStatement statement) {
|
||||
addIfNarrowing(statement.getCondition(), PsiType.BOOLEAN);
|
||||
super.visitWhileStatement(statement);
|
||||
}
|
||||
|
||||
final PsiType expectedTypeByParent = PsiTypesUtil.getExpectedTypeByParent(typeCast);
|
||||
PsiType opType = getOpTypeWithExpected(operand, expectedTypeByParent);
|
||||
@Override
|
||||
public void visitResourceExpression(PsiResourceExpression expression) {
|
||||
addIfNarrowing(expression.getExpression(), null);
|
||||
super.visitResourceExpression(expression);
|
||||
}
|
||||
|
||||
if (opType == null) return;
|
||||
|
||||
if (operand instanceof PsiFunctionalExpression) {
|
||||
if (expectedTypeByParent != null) {
|
||||
if (expectedTypeByParent.equals(castTo)) {
|
||||
addToResults(typeCast);
|
||||
return;
|
||||
@Override
|
||||
public void visitExpressionStatement(PsiExpressionStatement statement) {
|
||||
if (!(statement.getParent() instanceof PsiSwitchLabeledRuleStatement)) {
|
||||
addIfNarrowing(statement.getExpression(), null);
|
||||
}
|
||||
super.visitExpressionStatement(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameValuePair(PsiNameValuePair pair) {
|
||||
PsiAnnotationMemberValue value = pair.getValue();
|
||||
if (value instanceof PsiExpression) {
|
||||
addIfNarrowing((PsiExpression)value, null);
|
||||
}
|
||||
super.visitNameValuePair(pair);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambdaExpression(PsiLambdaExpression expression) {
|
||||
if (!(PsiUtil.skipParenthesizedExprUp(expression.getParent()) instanceof PsiExpressionList)) {
|
||||
PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(expression);
|
||||
if (method != null) {
|
||||
PsiType returnType = method.getReturnType();
|
||||
if (returnType != null) {
|
||||
List<PsiExpression> returns = LambdaUtil.getReturnExpressions(expression);
|
||||
for (PsiExpression aReturn : returns) {
|
||||
PsiExpression returnInLambda = deparenthesizeExpression(aReturn);
|
||||
if (returnInLambda instanceof PsiTypeCastExpression) {
|
||||
PsiExpression operand = getInnerMostOperand(returnInLambda);
|
||||
if (operand != null && returnType.equals(operand.getType())) {
|
||||
addToResults((PsiTypeCastExpression)returnInLambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!TypeConversionUtil.isAssignable(castTo, expectedTypeByParent, false)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent instanceof PsiExpressionStatement &&
|
||||
parent.getParent() instanceof PsiSwitchLabeledRuleStatement &&
|
||||
!castTo.equals(PsiTypesUtil.getExpectedTypeByParent(parent))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addIfNarrowing(typeCast, opType, expectedTypeByParent);
|
||||
super.visitLambdaExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -791,13 +808,7 @@ public class RedundantCastUtil {
|
||||
visitConditional((PsiTypeCastExpression)elseExpression, conditionalExpression, getInnerMostOperand(thenExpression));
|
||||
}
|
||||
|
||||
PsiExpression condition = deparenthesizeExpression(conditionalExpression.getCondition());
|
||||
if (condition instanceof PsiTypeCastExpression) {
|
||||
PsiExpression operand = getInnerMostOperand(((PsiTypeCastExpression)condition).getOperand());
|
||||
if (operand != null) {
|
||||
addIfNarrowing(((PsiTypeCastExpression)condition), operand.getType(), PsiType.BOOLEAN);
|
||||
}
|
||||
}
|
||||
addIfNarrowing(conditionalExpression.getCondition(), PsiType.BOOLEAN);
|
||||
super.visitConditionalExpression(conditionalExpression);
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -5,5 +5,13 @@ class RedundantCast {
|
||||
Object o = switch (matchType) {
|
||||
default -> (Predicate<Object>) target -> target == null;
|
||||
};
|
||||
Predicate<Object> o1 = switch (matchType) {
|
||||
default -> (<warning descr="Casting 'target -> {...}' to 'Predicate<Object>' is redundant">Predicate<Object></warning>) target -> target == null;
|
||||
};
|
||||
|
||||
Predicate<Object> o2 = switch (matchType) {
|
||||
default:
|
||||
yield (<warning descr="Casting 'target -> {...}' to 'Predicate<Object>' is redundant">Predicate<Object></warning>) target -> target == null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@ class X {
|
||||
void foo(String str) {}
|
||||
|
||||
void test(Object obj, boolean b) {
|
||||
foo((Object)(b ? obj : (<error descr="Expression expected">)</error>));
|
||||
foo((<warning descr="Casting '(b ? obj : ())' to 'Object' is redundant">Object</warning>)(b ? obj : (<error descr="Expression expected">)</error>));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class MyTest {
|
||||
|
||||
void m() {
|
||||
assert (<warning descr="Casting '(boolean)(boolean)(new Object() != null)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(boolean)(new Object() != null)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(new Object() != null)' to 'boolean' is redundant">boolean</warning>) (new Object() != null) : (<warning descr="Casting '(CharSequence)(String)\"message\"' to 'String' is redundant">String</warning>)(<warning descr="Casting '(String)\"message\"' to 'CharSequence' is redundant">CharSequence</warning>)(<warning descr="Casting '\"message\"' to 'String' is redundant">String</warning>)"message";
|
||||
if ((<warning descr="Casting '(boolean)(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(1 != 2)' to 'boolean' is redundant">boolean</warning>) (1 != 2)) {
|
||||
for(String string : ((<warning descr="Casting 'new String{\"a\", \"b\", (String)\"c\"}' to 'String[]' is redundant">String[]</warning>)new String[] {"a", "b", (<warning descr="Casting '\"c\"' to 'String' is redundant">String</warning>)"c"})) {
|
||||
do {
|
||||
while ((<warning descr="Casting '(boolean)(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(1 != 2)' to 'boolean' is redundant">boolean</warning>) (1 != 2)) {
|
||||
<error descr="Not a statement">(<warning descr="Casting 'MyTest.class.toString()' to 'String' is redundant">String</warning>)MyTest.class.toString();</error>
|
||||
}
|
||||
} while ((<warning descr="Casting '(boolean)(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(boolean)(1 != 2)' to 'boolean' is redundant">boolean</warning>)(<warning descr="Casting '(1 != 2)' to 'boolean' is redundant">boolean</warning>) (1 != 2));
|
||||
}
|
||||
}
|
||||
CharSequence sequence = "null";
|
||||
I ii = () -> (<warning descr="Casting 'sequence' to 'String' is redundant">String</warning>) sequence;
|
||||
}
|
||||
|
||||
interface I {
|
||||
CharSequence foo();
|
||||
}
|
||||
}
|
||||
@@ -50,4 +50,5 @@ public class RedundantCast18Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testInferenceIncompatibilityWithoutCast() { doTest();}
|
||||
public void testCastToPrimitive() { doTest();}
|
||||
public void testParenthesisAroundConditional() { doTest();}
|
||||
public void testMiscStatements() { doTest();}
|
||||
}
|
||||
Reference in New Issue
Block a user