Skip to content

Commit 36ed471

Browse files
committed
Fix BigDecimalLiteralDouble for boxed floating-point values
Signed-off-by: Vinod Kumar <codingkiddo@gmail.com>
1 parent 6f96cef commit 36ed471

2 files changed

Lines changed: 59 additions & 8 deletions

File tree

core/src/main/java/com/google/errorprone/bugpatterns/BigDecimalLiteralDouble.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import com.google.errorprone.matchers.Matcher;
2828
import com.google.errorprone.matchers.Matchers;
2929
import com.google.errorprone.util.ASTHelpers;
30+
import com.sun.tools.javac.code.Type;
31+
import javax.lang.model.type.TypeKind;
3032
import com.sun.source.tree.ExpressionTree;
3133
import com.sun.source.tree.NewClassTree;
3234
import com.sun.source.tree.Tree.Kind;
@@ -54,12 +56,27 @@ public class BigDecimalLiteralDouble extends BugChecker implements NewClassTreeM
5456
// Matches literals and unary +/- followed by a literal, since most people conceptually think of
5557
// -1.0 as a literal. Doesn't handle nested unary operators as new BigDecimal(String) doesn't
5658
// accept multiple unary prefixes.
57-
private static boolean floatingPointArgument(ExpressionTree tree) {
58-
if (tree.getKind() == Kind.UNARY_PLUS || tree.getKind() == Kind.UNARY_MINUS) {
59-
tree = ((UnaryTree) tree).getExpression();
60-
}
61-
return tree.getKind() == Kind.DOUBLE_LITERAL || tree.getKind() == Kind.FLOAT_LITERAL;
62-
}
59+
private static boolean floatingPointArgument(ExpressionTree tree, VisitorState state) {
60+
if (tree.getKind() == Kind.UNARY_PLUS || tree.getKind() == Kind.UNARY_MINUS) {
61+
tree = ((UnaryTree) tree).getExpression();
62+
}
63+
64+
if (tree.getKind() == Kind.DOUBLE_LITERAL || tree.getKind() == Kind.FLOAT_LITERAL) {
65+
return true;
66+
}
67+
68+
Type type = ASTHelpers.getType(tree);
69+
if (type == null) {
70+
return false;
71+
}
72+
73+
if (type.getKind() == TypeKind.DOUBLE || type.getKind() == TypeKind.FLOAT) {
74+
return true;
75+
}
76+
77+
return ASTHelpers.isSameType(type, state.getTypeFromString("java.lang.Double"), state)
78+
|| ASTHelpers.isSameType(type, state.getTypeFromString("java.lang.Float"), state);
79+
}
6380

6481
@Override
6582
public Description matchNewClass(NewClassTree tree, VisitorState state) {
@@ -68,11 +85,19 @@ public Description matchNewClass(NewClassTree tree, VisitorState state) {
6885
}
6986

7087
ExpressionTree arg = getOnlyElement(tree.getArguments());
71-
if (!floatingPointArgument(arg)) {
88+
89+
if (!floatingPointArgument(arg, state)) {
7290
return Description.NO_MATCH;
7391
}
7492

75-
return createDescription(arg, state);
93+
if (arg.getKind() == Kind.DOUBLE_LITERAL
94+
|| arg.getKind() == Kind.FLOAT_LITERAL
95+
|| arg.getKind() == Kind.UNARY_PLUS
96+
|| arg.getKind() == Kind.UNARY_MINUS) {
97+
return createDescription(arg, state);
98+
}
99+
100+
return buildDescription(arg).build();
76101
}
77102

78103
private Description createDescription(ExpressionTree arg, VisitorState state) {

core/src/test/java/com/google/errorprone/bugpatterns/BigDecimalLiteralDoubleTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,30 @@ void test() {
9090
&& message.contains("new BigDecimal(\"0.99\")"))
9191
.doTest();
9292
}
93+
94+
@Test
95+
public void losesPrecision_boxedFloatingPoint() {
96+
compilationHelper
97+
.addSourceLines(
98+
"Test.java",
99+
"""
100+
import java.math.BigDecimal;
101+
102+
class Test {
103+
void test() {
104+
Double boxedD = 0.1;
105+
// BUG: Diagnostic contains: new BigDecimal(double) loses precision
106+
new BigDecimal(boxedD);
107+
108+
Float boxedF = 0.1f;
109+
// BUG: Diagnostic contains: new BigDecimal(double) loses precision
110+
new BigDecimal(boxedF);
111+
112+
// BUG: Diagnostic contains: new BigDecimal(double) loses precision
113+
new BigDecimal((Float) 0.3f);
114+
}
115+
}
116+
""")
117+
.doTest();
118+
}
93119
}

0 commit comments

Comments
 (0)