mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java redundant cast: skip multiple casts in one expression (IDEA-159178)
GitOrigin-RevId: f2c01d1645aaa7082a90d8d06cd119d9aa43b90a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c2ec0c2e78
commit
269ea8783d
@@ -132,38 +132,44 @@ public class RedundantCastUtil {
|
||||
IElementType tokenType = expression.getOperationTokenType();
|
||||
PsiExpression[] operands = expression.getOperands();
|
||||
if (operands.length >= 2) {
|
||||
PsiType lType = operands[0].getType();
|
||||
processBinaryExpressionOperand(deparenthesizeExpression(operands[0]), operands[1].getType(), tokenType);
|
||||
PsiType lType = processBinaryExpressionOperand(deparenthesizeExpression(operands[0]), operands[1].getType(), tokenType);
|
||||
|
||||
for (int i = 1; i < operands.length; i++) {
|
||||
PsiExpression operand = deparenthesizeExpression(operands[i]);
|
||||
if (operand == null) continue;
|
||||
processBinaryExpressionOperand(operand, lType, tokenType);
|
||||
lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, operand.getType(), tokenType, true);
|
||||
PsiType rType = processBinaryExpressionOperand(operand, lType, tokenType);
|
||||
lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, rType, tokenType, true);
|
||||
}
|
||||
}
|
||||
processNestedCasts(expression.getOperands());
|
||||
super.visitPolyadicExpression(expression);
|
||||
}
|
||||
|
||||
private void processBinaryExpressionOperand(final PsiExpression operand,
|
||||
final PsiType otherType,
|
||||
final IElementType binaryToken) {
|
||||
private @Nullable PsiType processBinaryExpressionOperand(final PsiExpression operand,
|
||||
final PsiType otherType,
|
||||
final IElementType binaryToken) {
|
||||
if (operand instanceof PsiTypeCastExpression) {
|
||||
PsiTypeCastExpression typeCast = (PsiTypeCastExpression)operand;
|
||||
PsiExpression toCast = typeCast.getOperand();
|
||||
if (toCast != null && TypeConversionUtil.isBinaryOperatorApplicable(binaryToken, toCast.getType(), otherType, false)) {
|
||||
if (toCast != null && otherType != null && TypeConversionUtil.isBinaryOperatorApplicable(binaryToken, toCast.getType(), otherType, false)) {
|
||||
addToResults(typeCast);
|
||||
return toCast.getType();
|
||||
}
|
||||
}
|
||||
return operand != null ? operand.getType() : null;
|
||||
}
|
||||
|
||||
private void processPossibleTypeCast(PsiExpression rExpr, @Nullable PsiType lType) {
|
||||
rExpr = deparenthesizeExpression(rExpr);
|
||||
if (rExpr instanceof PsiTypeCastExpression) {
|
||||
PsiExpression castOperand = ((PsiTypeCastExpression)rExpr).getOperand();
|
||||
PsiExpression castOperand = PsiUtil.skipParenthesizedExprDown(((PsiTypeCastExpression)rExpr).getOperand());
|
||||
if (castOperand != null) {
|
||||
PsiType operandType;
|
||||
if (castOperand instanceof PsiTypeCastExpression) {
|
||||
final PsiExpression nestedCastOperand = ((PsiTypeCastExpression)castOperand).getOperand();
|
||||
PsiExpression nestedCastOperand = ((PsiTypeCastExpression)castOperand).getOperand();
|
||||
while (nestedCastOperand instanceof PsiTypeCastExpression) {
|
||||
nestedCastOperand = PsiUtil.skipParenthesizedExprDown(((PsiTypeCastExpression)nestedCastOperand).getOperand());
|
||||
}
|
||||
operandType = nestedCastOperand != null ? nestedCastOperand.getType() : null;
|
||||
}
|
||||
else if (castOperand instanceof PsiFunctionalExpression && lType != null) {
|
||||
@@ -298,30 +304,17 @@ public class RedundantCastUtil {
|
||||
PsiParameter[] parameters = oldMethod.getParameterList().getParameters();
|
||||
|
||||
try {
|
||||
PsiCall newCall = null;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
ProgressManager.checkCanceled();
|
||||
final PsiExpression arg = deparenthesizeExpression(args[i]);
|
||||
if (arg instanceof PsiTypeCastExpression) {
|
||||
PsiTypeCastExpression cast = (PsiTypeCastExpression)arg;
|
||||
final PsiType typeByParent = PsiTypesUtil.getExpectedTypeByParent(expression);
|
||||
final PsiCall newCall;
|
||||
if (typeByParent != null) {
|
||||
newCall = (PsiCall)LambdaUtil.copyWithExpectedType(expression, typeByParent);
|
||||
}
|
||||
else {
|
||||
final PsiCall call = LambdaUtil.treeWalkUp(expression);
|
||||
if (call != null) {
|
||||
Object marker = new Object();
|
||||
PsiTreeUtil.mark(expression, marker);
|
||||
final PsiCall callCopy = LambdaUtil.copyTopLevelCall(call);
|
||||
if (callCopy == null) return;
|
||||
newCall = (PsiCall)PsiTreeUtil.releaseMark(callCopy, marker);
|
||||
if (newCall == null) return;
|
||||
}
|
||||
else {
|
||||
newCall = (PsiCall)expression.copy();
|
||||
}
|
||||
if (newCall == null) {
|
||||
newCall = copyCallExpression(expression, typeByParent);
|
||||
}
|
||||
if (newCall == null) return;
|
||||
final PsiExpressionList argList = newCall.getArgumentList();
|
||||
LOG.assertTrue(argList != null);
|
||||
PsiExpression[] newArgs = argList.getExpressions();
|
||||
@@ -371,6 +364,9 @@ public class RedundantCastUtil {
|
||||
elseType != null && targetType.isAssignableFrom(elseType)) {
|
||||
addToResults(cast);
|
||||
}
|
||||
else {
|
||||
newArg.replace(arg);
|
||||
}
|
||||
}
|
||||
else if (!(newArg instanceof PsiFunctionalExpression)) {
|
||||
addToResults(cast);
|
||||
@@ -387,8 +383,14 @@ public class RedundantCastUtil {
|
||||
if (Comparing.equal(castType, ((PsiFunctionalExpression)newArg).getGroundTargetType(newArgType))) {
|
||||
addToResults(cast);
|
||||
}
|
||||
else {
|
||||
newArg.replace(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
newArgs[i].replace(arg);
|
||||
}
|
||||
}
|
||||
else if (arg instanceof PsiLambdaExpression) {
|
||||
final PsiType interfaceType = ((PsiLambdaExpression)arg).getFunctionalInterfaceType();
|
||||
@@ -425,6 +427,10 @@ public class RedundantCastUtil {
|
||||
return;
|
||||
}
|
||||
|
||||
processNestedCasts(args);
|
||||
}
|
||||
|
||||
private void processNestedCasts(PsiExpression[] args) {
|
||||
for (PsiExpression arg : args) {
|
||||
if (arg instanceof PsiTypeCastExpression) {
|
||||
PsiExpression castOperand = ((PsiTypeCastExpression)arg).getOperand();
|
||||
@@ -438,6 +444,26 @@ public class RedundantCastUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiCall copyCallExpression(PsiCall expression, PsiType typeByParent) {
|
||||
if (typeByParent != null) {
|
||||
return (PsiCall)LambdaUtil.copyWithExpectedType(expression, typeByParent);
|
||||
}
|
||||
else {
|
||||
final PsiCall call = LambdaUtil.treeWalkUp(expression);
|
||||
if (call != null) {
|
||||
Object marker = new Object();
|
||||
PsiTreeUtil.mark(expression, marker);
|
||||
final PsiCall callCopy = LambdaUtil.copyTopLevelCall(call);
|
||||
if (callCopy == null) return null;
|
||||
return (PsiCall)PsiTreeUtil.releaseMark(callCopy, marker);
|
||||
}
|
||||
else {
|
||||
return (PsiCall)expression.copy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processLambdaReturnExpression(PsiCall expression,
|
||||
int i,
|
||||
PsiType interfaceType,
|
||||
@@ -574,6 +600,7 @@ public class RedundantCastUtil {
|
||||
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 PsiLambdaExpression) return;
|
||||
|
||||
|
||||
@@ -8,3 +8,27 @@ class Test {
|
||||
f((String)o, (<warning descr="Casting 'o' to 'String' is redundant">String</warning>)o);
|
||||
}
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
public Test1(int width, int height) {
|
||||
this((<warning descr="Casting 'width' to 'double' is redundant">double</warning>)width, (double)height);
|
||||
}
|
||||
|
||||
private Test1(double width, double height) { }
|
||||
|
||||
private String foo(Object[] array, int index1, int index2) {
|
||||
return (<warning descr="Casting 'array[index1]' to 'String' is redundant">String</warning>) array[index1] + (String) array[index2];
|
||||
}
|
||||
|
||||
private static void triple(Object obj) {
|
||||
String s = (String) (<warning descr="Casting '(String)obj' to 'CharSequence' is redundant">CharSequence</warning>) (<warning descr="Casting 'obj' to 'String' is redundant">String</warning>) obj;
|
||||
}
|
||||
|
||||
private Integer parenthesis(Object[] array, int index) {
|
||||
return (Integer) ((<warning descr="Casting 'array[index]' to 'Integer' is redundant">Integer</warning>) array[index]);
|
||||
}
|
||||
|
||||
private String binary(Object[] array, int index1, int index2) {
|
||||
return (<warning descr="Casting 'array[index1]' to 'String' is redundant">String</warning>) array[index1] + (String) array[index2];
|
||||
}
|
||||
}
|
||||
@@ -27,5 +27,5 @@ class Test {
|
||||
final Set<String> strings = null;
|
||||
final Pair<Set<String>, Set<String>> x = Boolean.TRUE.booleanValue()
|
||||
? Pair.create(strings, strings)
|
||||
: Pair.create(((<warning descr="Casting 'null' to 'Set<String>' is redundant">Set<String></warning>) null), (<warning descr="Casting 'null' to 'Set<String>' is redundant">Set<String></warning>) null); //both casts are marked, but one is required for correct inference
|
||||
: Pair.create(((<warning descr="Casting 'null' to 'Set<String>' is redundant">Set<String></warning>) null), (Set<String>) null); //both casts are marked, but one is required for correct inference
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user