mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-116910 (Invalid "unnecessary explicit numeric cast" warning)
This commit is contained in:
+4
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2013 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.
|
||||
@@ -24,29 +24,13 @@ import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CastThatLosesPrecisionInspection extends BaseInspection {
|
||||
|
||||
/**
|
||||
* @noinspection StaticCollection
|
||||
*/
|
||||
private static final Map<PsiType, Integer> typePrecisions = new HashMap<PsiType, Integer>(7);
|
||||
|
||||
static {
|
||||
typePrecisions.put(PsiType.BYTE, 1);
|
||||
typePrecisions.put(PsiType.CHAR, 2);
|
||||
typePrecisions.put(PsiType.SHORT, 2);
|
||||
typePrecisions.put(PsiType.INT, 3);
|
||||
typePrecisions.put(PsiType.LONG, 4);
|
||||
typePrecisions.put(PsiType.FLOAT, 5);
|
||||
typePrecisions.put(PsiType.DOUBLE, 6);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PublicField"})
|
||||
public boolean ignoreIntegerCharCasts = false;
|
||||
|
||||
@@ -81,8 +65,7 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
|
||||
return new CastThatLosesPrecisionVisitor();
|
||||
}
|
||||
|
||||
private class CastThatLosesPrecisionVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private class CastThatLosesPrecisionVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
|
||||
@@ -95,10 +78,7 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
final PsiType operandType = operand.getType();
|
||||
if (!ClassUtils.isPrimitiveNumericType(operandType)) {
|
||||
return;
|
||||
}
|
||||
if (hasLowerPrecision(operandType, castType)) {
|
||||
if (!ClassUtils.isPrimitiveNumericType(operandType) || !TypeUtils.isNarrowingConversion(operandType, castType)) {
|
||||
return;
|
||||
}
|
||||
if (ignoreIntegerCharCasts) {
|
||||
@@ -129,12 +109,6 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
|
||||
registerError(castTypeElement, operandType);
|
||||
}
|
||||
|
||||
private boolean hasLowerPrecision(PsiType operandType, PsiType castType) {
|
||||
final Integer operandPrecision = typePrecisions.get(operandType);
|
||||
final Integer castPrecision = typePrecisions.get(castType);
|
||||
return operandPrecision.intValue() <= castPrecision.intValue();
|
||||
}
|
||||
|
||||
private boolean valueIsContainableInType(Number value, PsiType type) {
|
||||
final long longValue = value.longValue();
|
||||
final double doubleValue = value.doubleValue();
|
||||
|
||||
+27
-40
@@ -28,6 +28,7 @@ import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -158,17 +159,21 @@ public class UnnecessaryExplicitNumericCastInspection extends BaseInspection {
|
||||
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)parent;
|
||||
final IElementType tokenType = polyadicExpression.getOperationTokenType();
|
||||
if (binaryPromotionOperators.contains(tokenType)) {
|
||||
if (TypeUtils.isNarrowingConversion(operandType, castType)) {
|
||||
return true;
|
||||
}
|
||||
if (PsiType.INT.equals(castType)) {
|
||||
return PsiType.LONG.equals(operandType) || PsiType.FLOAT.equals(operandType) || PsiType.DOUBLE.equals(operandType);
|
||||
}
|
||||
if (PsiType.LONG.equals(castType) || PsiType.FLOAT.equals(castType) || PsiType.DOUBLE.equals(castType)) {
|
||||
final PsiExpression[] operands = polyadicExpression.getOperands();
|
||||
for (PsiExpression operand1 : operands) {
|
||||
if (!PsiTreeUtil.isAncestor(operand1, expression, false)) {
|
||||
final PsiType type = operand1.getType();
|
||||
if (castType.equals(type)) {
|
||||
return false;
|
||||
}
|
||||
if (PsiTreeUtil.isAncestor(operand1, expression, false)) {
|
||||
continue;
|
||||
}
|
||||
final PsiType type = operand1.getType();
|
||||
if (castType.equals(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,49 +288,31 @@ public class UnnecessaryExplicitNumericCastInspection extends BaseInspection {
|
||||
|
||||
static boolean isLegalAssignmentConversion(PsiExpression expression, PsiType assignmentType) {
|
||||
// JLS 5.2 Assignment Conversion
|
||||
final PsiType operandType = expression.getType();
|
||||
if (isLegalWideningConversion(expression, assignmentType)) {
|
||||
return true;
|
||||
}
|
||||
else if (PsiType.SHORT.equals(assignmentType)) {
|
||||
if (PsiType.INT.equals(operandType)) {
|
||||
final Object constant = ExpressionUtils.computeConstantExpression(expression);
|
||||
if (!(constant instanceof Integer)) {
|
||||
return false;
|
||||
}
|
||||
final int i = ((Integer)constant).intValue();
|
||||
if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
|
||||
// narrowing
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (PsiType.SHORT.equals(assignmentType)) {
|
||||
return canValueBeContained(expression, Short.MIN_VALUE, Short.MAX_VALUE);
|
||||
}
|
||||
else if (PsiType.CHAR.equals(assignmentType)) {
|
||||
if (PsiType.INT.equals(operandType)) {
|
||||
final Object constant = ExpressionUtils.computeConstantExpression(expression);
|
||||
if (!(constant instanceof Integer)) {
|
||||
return false;
|
||||
}
|
||||
final int i = ((Integer)constant).intValue();
|
||||
if (i >= Character.MIN_VALUE && i <= Character.MAX_VALUE) {
|
||||
// narrowing
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return canValueBeContained(expression, Character.MIN_VALUE, Character.MAX_VALUE);
|
||||
}
|
||||
else if (PsiType.BYTE.equals(assignmentType)) {
|
||||
if (PsiType.INT.equals(operandType)) {
|
||||
final Object constant = ExpressionUtils.computeConstantExpression(expression);
|
||||
if (!(constant instanceof Integer)) {
|
||||
return false;
|
||||
}
|
||||
final int i = ((Integer)constant).intValue();
|
||||
if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
|
||||
// narrowing
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return canValueBeContained(expression, Byte.MIN_VALUE, Byte.MAX_VALUE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean canValueBeContained(PsiExpression expression, int lowerBound, int upperBound) {
|
||||
final PsiType expressionType = expression.getType();
|
||||
if (!PsiType.INT.equals(expressionType)) {
|
||||
return false;
|
||||
}
|
||||
final Object constant = ExpressionUtils.computeConstantExpression(expression);
|
||||
if (!(constant instanceof Integer)) {
|
||||
return false;
|
||||
}
|
||||
final int i = ((Integer)constant).intValue();
|
||||
return i >= lowerBound && i <= upperBound;
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -23,8 +23,23 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TypeUtils {
|
||||
|
||||
private static final Map<PsiType, Integer> typePrecisions = new HashMap<PsiType, Integer>(7);
|
||||
|
||||
static {
|
||||
typePrecisions.put(PsiType.BYTE, 1);
|
||||
typePrecisions.put(PsiType.CHAR, 2);
|
||||
typePrecisions.put(PsiType.SHORT, 2);
|
||||
typePrecisions.put(PsiType.INT, 3);
|
||||
typePrecisions.put(PsiType.LONG, 4);
|
||||
typePrecisions.put(PsiType.FLOAT, 5);
|
||||
typePrecisions.put(PsiType.DOUBLE, 6);
|
||||
}
|
||||
|
||||
private TypeUtils() {}
|
||||
|
||||
public static boolean typeEquals(@NonNls @NotNull String typeName, @Nullable PsiType targetType) {
|
||||
@@ -50,6 +65,12 @@ public class TypeUtils {
|
||||
return getType(CommonClassNames.JAVA_LANG_STRING, context);
|
||||
}
|
||||
|
||||
public static boolean isNarrowingConversion(PsiType operandType, PsiType castType) {
|
||||
final Integer operandPrecision = typePrecisions.get(operandType);
|
||||
final Integer castPrecision = typePrecisions.get(castType);
|
||||
return operandPrecision.intValue() > castPrecision.intValue();
|
||||
}
|
||||
|
||||
public static boolean isJavaLangObject(@Nullable PsiType targetType) {
|
||||
return typeEquals(CommonClassNames.JAVA_LANG_OBJECT, targetType);
|
||||
}
|
||||
|
||||
+10
@@ -53,4 +53,14 @@ public class UnnecessaryExplicitNumericCast {
|
||||
float x = 2;
|
||||
target((int) x); // this line complains: 'x' unnecessarily cast to 'int'
|
||||
}
|
||||
|
||||
void a(float angleFromTo) {
|
||||
float f = (float) Math.cos(0.5) * 1.0f; // necessary
|
||||
final long l = (long) i() * 9L;
|
||||
float angle2 = angleFromTo + (float) (Math.PI / 2);
|
||||
}
|
||||
|
||||
int i() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -100,4 +100,11 @@
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unnecessary explicit numeric cast</problem_class>
|
||||
<description>''b'' unnecessarily cast to <code>int</code> #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>UnnecessaryExplicitNumericCast.java</file>
|
||||
<line>59</line>
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unnecessary explicit numeric cast</problem_class>
|
||||
<description>'i()' unnecessarily cast to <code>long</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
Reference in New Issue
Block a user