IG: add option to ignore casts from int 128-255 to byte (IDEA-174125)

This commit is contained in:
Bas Leijdekkers
2017-06-09 16:45:35 +02:00
parent dceb40cf32
commit cefdfab87b
5 changed files with 60 additions and 30 deletions
@@ -1203,8 +1203,8 @@ normalize.declaration.quickfix=Split into multiple declarations
remove.modifier.quickfix=Remove ''{0}'' modifier
replace.inheritance.with.delegation.quickfix=Replace inheritance with delegation
big.decimal.equals.replace.quickfix=Replace with 'compareTo()==0'
cast.that.loses.precision.problem.descriptor=Cast to <code>#ref</code> from ''{0}'' may result in loss of precision #loc
cast.that.loses.precision.negative.problem.descriptor=Cast to <code>#ref</code> from ''{0}'' may result in loss of precision #loc for negative argument
cast.that.loses.precision.problem.descriptor=Cast from ''{0}'' to <code>#ref</code> may result in loss of precision #loc
cast.that.loses.precision.negative.problem.descriptor=Cast from ''{0}'' to <code>#ref</code> may result in loss of precision for negative argument #loc
comparison.to.nan.problem.descriptor1=Comparison to <code>#ref</code> is always false #loc
comparison.to.nan.problem.descriptor2=Comparison to <code>#ref</code> is always true #loc
comparison.to.nan.replace.quickfix=Replace with 'isNaN()'
@@ -1686,6 +1686,7 @@ unnecessary.parentheses.conditional.option=Ignore parentheses around the conditi
field.may.be.final.display.name=Field may be 'final'
field.may.be.final.problem.descriptor=Field <code>#ref</code> may be 'final' #loc
cast.that.loses.precision.option=Ignore casts from int to char
ignore.overflowing.byte.casts.option=Ignore casts from int 128-255 to byte
variable.not.used.inside.if.display.name=Reference checked for 'null' is not used inside 'if'
variable.not.used.inside.if.problem.descriptor=<code>#ref</code> checked for 'null' is not used inside 'if' #loc
variable.not.used.inside.conditional.problem.descriptor=<code>#ref</code> checked for 'null' is not used inside conditional #loc
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2017 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.
@@ -18,7 +18,7 @@ package com.siyeh.ig.numeric;
import com.intellij.codeInspection.dataFlow.*;
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -39,6 +39,9 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean ignoreIntegerCharCasts = false;
@SuppressWarnings({"PublicField"})
public boolean ignoreOverflowingByteCasts = false;
@Pattern(VALID_ID_PATTERN)
@Override
@NotNull
@@ -58,15 +61,18 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
public String buildErrorString(Object... infos) {
final PsiType operandType = (PsiType)infos[0];
boolean negativeOnly = (boolean)infos[1];
return InspectionGadgetsBundle
.message(negativeOnly ? "cast.that.loses.precision.negative.problem.descriptor" : "cast.that.loses.precision.problem.descriptor",
operandType.getPresentableText());
return InspectionGadgetsBundle.message(negativeOnly ?
"cast.that.loses.precision.negative.problem.descriptor" :
"cast.that.loses.precision.problem.descriptor",
operandType.getPresentableText());
}
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("cast.that.loses.precision.option"),
this, "ignoreIntegerCharCasts");
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message("cast.that.loses.precision.option"), "ignoreIntegerCharCasts");
panel.addCheckbox(InspectionGadgetsBundle.message("ignore.overflowing.byte.casts.option"), "ignoreOverflowingByteCasts");
return panel;
}
@Override
@@ -90,10 +96,8 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
if (!ClassUtils.isPrimitiveNumericType(operandType) || !TypeUtils.isNarrowingConversion(operandType, castType)) {
return;
}
if (ignoreIntegerCharCasts) {
if (PsiType.INT.equals(operandType) && PsiType.CHAR.equals(castType)) {
return;
}
if (ignoreIntegerCharCasts && PsiType.INT.equals(operandType) && PsiType.CHAR.equals(castType)) {
return;
}
if (PsiType.LONG.equals(operandType) && PsiType.INT.equals(castType)) {
final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
@@ -107,6 +111,12 @@ public class CastThatLosesPrecisionInspection extends BaseInspection {
}
if (result instanceof Number) {
final Number number = (Number)result;
if (ignoreOverflowingByteCasts && PsiType.INT.equals(operandType) && PsiType.BYTE.equals(castType)) {
final int i = number.intValue();
if (i > Byte.MIN_VALUE && i <= 255) {
return;
}
}
if (valueIsContainableInType(number, castType)) {
return;
}
@@ -5,12 +5,13 @@ result in loss of precision. Such casts are not necessarily a problem, but may r
trace bugs if the loss of precision is unexpected.
<!-- tooltip end -->
<p>
Use the checkbox below to indicate that this inspection should ignore casts from
Use the first checkbox below to indicate that this inspection should ignore casts from
<b>int</b> to <b>char</b>.
This type of cast is often used when implementing I/O operations, because the
<b>read()</b> method of the class
<b>java.io.Reader</b> returns an <b>int</b>.
<p>
Use the second checkbox below to ignore casts of constant values 128-255 from <b>int</b> to <b>byte</b>.
Such values will overflow to negative numbers that still fit inside a byte.
</body>
</html>
@@ -12,29 +12,26 @@ public class CastThatLosesPrecision
int i;
char ch;
i = (<warning descr="Cast to 'int' from 'float' may result in loss of precision">int</warning>) f;
i = (<warning descr="Cast from 'float' to 'int' may result in loss of precision">int</warning>) f;
System.out.println("i = " + i);
ch = (<warning descr="Cast to 'char' from 'double' may result in loss of precision">char</warning>) d;
ch = (<warning descr="Cast from 'double' to 'char' may result in loss of precision">char</warning>) d;
System.out.println("ch = " + ch);
i = (<warning descr="Cast to 'int' from 'double' may result in loss of precision">int</warning>) d;
i = (<warning descr="Cast from 'double' to 'int' may result in loss of precision">int</warning>) d;
System.out.println("i = " + i);
i = (<warning descr="Cast to 'int' from 'long' may result in loss of precision">int</warning>) l;
i = (<warning descr="Cast from 'long' to 'int' may result in loss of precision">int</warning>) l;
System.out.println("i = " + i);
b = (<warning descr="Cast to 'byte' from 'long' may result in loss of precision">byte</warning>) l;
b = (<warning descr="Cast from 'long' to 'byte' may result in loss of precision">byte</warning>) l;
System.out.println("b = " + b);
l = (<warning descr="Cast to 'long' from 'double' may result in loss of precision">long</warning>) d;
l = (<warning descr="Cast from 'double' to 'long' may result in loss of precision">long</warning>) d;
System.out.println("l = " + l);
l = (<warning descr="Cast to 'long' from 'float' may result in loss of precision">long</warning>) f;
l = (<warning descr="Cast from 'float' to 'long' may result in loss of precision">long</warning>) f;
System.out.println("l = " + l);
d = (double) f;
System.out.println("d = " + d);
f = (<warning descr="Cast to 'float' from 'double' may result in loss of precision">float</warning>) d;
f = (<warning descr="Cast from 'double' to 'float' may result in loss of precision">float</warning>) d;
System.out.println("f = " + f);
}
@@ -52,7 +49,7 @@ public class CastThatLosesPrecision
System.out.println("i = " + i);
i = (int) 0L;
System.out.println("i = " + i);
b = (<warning descr="Cast to 'byte' from 'long' may result in loss of precision">byte</warning>) l;
b = (<warning descr="Cast from 'long' to 'byte' may result in loss of precision">byte</warning>) l;
System.out.println("b = " + b);
l = (long) 0.0;
@@ -74,7 +71,7 @@ public class CastThatLosesPrecision
@Override
public int hashCode() {
int result = (int) (aLong ^ (aLong >>> 32));
long temp = d != +0.0d ? (<warning descr="Cast to 'int' from 'double' may result in loss of precision">int</warning>) d : 0L;
long temp = d != +0.0d ? (<warning descr="Cast from 'double' to 'int' may result in loss of precision">int</warning>) d : 0L;
result = 31 * result + (int) (temp ^ temp >>> 32);
return result;
}
@@ -83,7 +80,7 @@ public class CastThatLosesPrecision
if (longNumberOfAgents > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Too many agents: " + longNumberOfAgents);
}
int intNumberOfAgents = (<warning descr="Cast to 'int' from 'long' may result in loss of precision for negative argument">int</warning>)longNumberOfAgents;
int intNumberOfAgents = (<warning descr="Cast from 'long' to 'int' may result in loss of precision for negative argument">int</warning>)longNumberOfAgents;
System.out.println(intNumberOfAgents);
}
@@ -97,4 +94,8 @@ public class CastThatLosesPrecision
int intNumberOfAgents = (int)longNumberOfAgents;
System.out.println(intNumberOfAgents);
}
void bytes() {
byte[] bytes = { (byte) 0xb2, (byte) 0x80 };
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.InspectionProfileEntry;
@@ -13,6 +28,8 @@ public class CastThatLosesPrecisionInspectionTest extends LightInspectionTestCas
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new CastThatLosesPrecisionInspection();
final CastThatLosesPrecisionInspection inspection = new CastThatLosesPrecisionInspection();
inspection.ignoreOverflowingByteCasts = true;
return inspection;
}
}