Skip to content

Commit 51b1dde

Browse files
SONARJAVA-5522 DefaultInitializedFieldCheck handles underscores in float/double (#5116)
Co-authored-by: gtoison <guillaume.toison@tobam.fr>
1 parent d5bbf58 commit 51b1dde

4 files changed

Lines changed: 81 additions & 2 deletions

File tree

java-checks-test-sources/default/src/main/java/checks/DefaultInitializedFieldCheckSample.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,26 @@ class DefaultInitializedFieldCheckSample {
2121
float f1 = 0.f; // Noncompliant {{Remove this initialization to "0.f", the compiler will do that for you.}}
2222
float f2 = 1.f;
2323
float f3;
24+
float f4 = 1_000_000F; // Compliant, not 0
25+
float f5 = 1_000_000_000_000_000_000f; // Compliant, not 0
26+
float f6 = 1_000_000; // Compliant, not 0
27+
float f7 = 0_000_000; // Noncompliant {{Remove this initialization to "0_000_000", the compiler will do that for you.}}
28+
float f8 = 0_000_000f; // Noncompliant {{Remove this initialization to "0_000_000f", the compiler will do that for you.}}
29+
float f9 = (float) 1_000_000d; // Compliant, not 0
30+
float f10 = 123_456e-7f; // Compliant, not 0
31+
float f11 = 1_000.0f; // Compliant, not 0
2432
double d = 0.; // Noncompliant {{Remove this initialization to "0.", the compiler will do that for you.}}
2533
double d1 = 1.;
2634
double d2;
2735
double d3 = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001; // Compliant, not 0
36+
double d4 = 1_000_000D; // Compliant, not 0
37+
double d5 = 1_000_000_000_000_000_000d; // Compliant, not 0
38+
double d6 = 1_000_000; // Compliant, not 0
39+
double d7 = 0_000_000; // Noncompliant {{Remove this initialization to "0_000_000", the compiler will do that for you.}}
40+
double d8 = 0_000_000d; // Noncompliant {{Remove this initialization to "0_000_000d", the compiler will do that for you.}}
41+
double d9 = 1_000_000f; // Compliant, not 0
42+
double d10 = 123_456e-7d; // Compliant, not 0
43+
double d11 = 1_000.0f; // Compliant, not 0
2844
char c = 0; // Noncompliant {{Remove this initialization to "0", the compiler will do that for you.}}
2945
char c1 = '\u0000'; // Noncompliant {{Remove this initialization to "'\u0000'", the compiler will do that for you.}}
3046
// ^^^^^^^^

java-checks/src/main/java/org/sonar/java/checks/DefaultInitializedFieldCheck.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ private static Optional<String> getIfDefault(ExpressionTree expression, boolean
7979
.flatMap(numericalValue -> literalValue(expression));
8080
case FLOAT_LITERAL,
8181
DOUBLE_LITERAL:
82-
return literalValue(expression)
83-
.filter(numericalValue -> Double.doubleToLongBits(Double.valueOf(numericalValue)) == 0);
82+
return Optional.ofNullable(LiteralUtils.doubleLiteralValue(expression))
83+
.filter(numericalValue -> Double.doubleToLongBits(numericalValue) == 0)
84+
.flatMap(numericalValue -> literalValue(expression));
8485
case TYPE_CAST:
8586
return getIfDefault(((TypeCastTree) expression).expression(), isPrimitive);
8687
default:

java-frontend/src/main/java/org/sonar/java/model/LiteralUtils.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ public static Long longLiteralValue(ExpressionTree tree) {
8585
return null;
8686
}
8787

88+
@CheckForNull
89+
public static Double doubleLiteralValue(ExpressionTree expression) {
90+
int sign = 1;
91+
if (expression.is(Kind.UNARY_MINUS, Kind.UNARY_PLUS)) {
92+
sign = expression.is(Kind.UNARY_MINUS) ? -1 : 1;
93+
expression = ((UnaryExpressionTree) expression).expression();
94+
}
95+
96+
if (expression.is(Kind.FLOAT_LITERAL, Kind.DOUBLE_LITERAL)) {
97+
String value = ((LiteralTree) expression).value().replace("_", "");
98+
99+
return sign*Double.parseDouble(value);
100+
}
101+
return null;
102+
}
103+
88104
@CheckForNull
89105
private static Integer minus(@Nullable Integer nullableInteger) {
90106
return nullableInteger == null ? null : -nullableInteger;

java-frontend/src/test/java/org/sonar/java/model/LiteralUtilsTest.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@ static void beforeAll() {
8585
long y17 = 0XFFL;
8686
long y18 = 0B1100110L;
8787

88+
float f1 = 0f;
89+
float f2 = 0.f;
90+
float f3 = 123.45f;
91+
float f4 = 1_000_000F;
92+
float f5 = +1_000_000_000_000_000_000f;
93+
float f6 = -1_000_000F;
94+
float f7 = -.9f;
95+
float f8 = 0x1.2p3f;
96+
float f9 = 123_456e-7f;
97+
float f10 = (float)0;
98+
float f11 = 0;
99+
float f13 = f1 + 0;
100+
double d1 = 0.;
101+
double d2 = 1.d;
102+
double d3 = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;
103+
double d4 = -1_000_000D;
104+
double d5 = +1_000_000_000_000_000_000d;
105+
double d6 = 23_456e-7d;
106+
double d7 = 0x1.2p3;
107+
double d8 = 0;
108+
double d9 = d1 + 0;
109+
88110
String s1 = "";
89111
String s2 = " ";
90112
String s3 = "not_empty";
@@ -116,6 +138,30 @@ void test_int_and_long_value() {
116138
}
117139
}
118140

141+
@Test
142+
void test_float_value() {
143+
Double[] expectedValues = {0d, 0.d, 123.45d, 1_000_000D, 1_000_000_000_000_000_000d, -1_000_000d, -.9d, 0x1.2p3d, 123_456e-7d, null, null, null};
144+
int idx = 0;
145+
146+
for (VariableTree variableTree : variables) {
147+
if (variableTree.simpleName().name().startsWith("f")) {
148+
assertThat(LiteralUtils.doubleLiteralValue(variableTree.initializer())).isEqualTo(expectedValues[idx++]);
149+
}
150+
}
151+
}
152+
153+
@Test
154+
void test_double_value() {
155+
Double[] expectedValues = {0., 1.d, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, -1_000_000D, +1_000_000_000_000_000_000d, 23_456e-7d, 0x1.2p3, null , null};
156+
int idx = 0;
157+
158+
for (VariableTree variableTree : variables) {
159+
if (variableTree.simpleName().name().startsWith("d")) {
160+
assertThat(LiteralUtils.doubleLiteralValue(variableTree.initializer())).isEqualTo(expectedValues[idx++]);
161+
}
162+
}
163+
}
164+
119165
/**
120166
* Binary, hex and octal int literals are allowed when they fit into 32-bits (jls11 - §3.10.1)
121167
*/

0 commit comments

Comments
 (0)