Skip to content

Commit b69f063

Browse files
authored
Fix binary operations in MathTargetType (#9)
1 parent 57b706c commit b69f063

3 files changed

Lines changed: 51 additions & 6 deletions

File tree

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ errorprone-checks
33

44
A collection of custom [errorprone] checks.
55

6-
76
## Usage
87
- Add Consensys maven dependency
98
```groovy

src/main/java/tech/pegasys/tools/epchecks/MathTargetType.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
1616
import static com.google.errorprone.matchers.Matchers.staticMethod;
1717

18+
import java.util.List;
1819
import javax.lang.model.type.TypeKind;
1920

2021
import com.google.auto.service.AutoService;
@@ -34,6 +35,7 @@
3435
import com.sun.source.tree.Tree;
3536
import com.sun.source.tree.TypeCastTree;
3637
import com.sun.source.tree.VariableTree;
38+
import com.sun.source.util.TreePath;
3739
import com.sun.tools.javac.code.Type;
3840

3941
@AutoService(BugChecker.class)
@@ -52,11 +54,20 @@ public class MathTargetType extends BugChecker implements MethodInvocationTreeMa
5254
.namedAnyOf(
5355
"min", "max", "addExact", "subtractExact", "multiplyExact", "floorDiv", "floorMod");
5456

57+
private static final List<Tree.Kind> COMPARISONS =
58+
List.of(
59+
Tree.Kind.EQUAL_TO,
60+
Tree.Kind.NOT_EQUAL_TO,
61+
Tree.Kind.GREATER_THAN,
62+
Tree.Kind.GREATER_THAN_EQUAL,
63+
Tree.Kind.LESS_THAN,
64+
Tree.Kind.LESS_THAN_EQUAL);
65+
5566
@Override
5667
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
5768
if (POTENTIALLY_CONFUSED_MATH_FUNC.matches(tree, state)) {
5869
Tree parent = state.getPath().getParentPath().getLeaf();
59-
Type type = getTargetType(tree, parent, state);
70+
Type type = getTargetType(tree, parent, state, state.getPath().getParentPath());
6071
if (type != null && !anyMethodArgIs(tree, state, type.getKind())) {
6172
String typeName = type.getKind().toString().toLowerCase();
6273
return buildDescription(tree)
@@ -79,21 +90,32 @@ private boolean anyMethodArgIs(MethodInvocationTree tree, VisitorState state, Ty
7990
return false;
8091
}
8192

82-
private Type getTargetType(Tree original, Tree tree, VisitorState state) {
93+
private Type getTargetType(Tree prev, Tree tree, VisitorState state, TreePath path) {
8394
if (tree instanceof AssignmentTree) {
8495
AssignmentTree assignmentTree = (AssignmentTree) tree;
8596
return ASTHelpers.getType(assignmentTree.getVariable());
8697
}
8798

8899
if (tree instanceof BinaryTree) {
100+
// In the case of comparisons, the target type will be the
101+
// other side of the operation.
102+
BinaryTree binaryTree = (BinaryTree) tree;
103+
if (COMPARISONS.contains(tree.getKind())) {
104+
if (binaryTree.getLeftOperand().equals(prev)) {
105+
return ASTHelpers.getType(binaryTree.getRightOperand());
106+
}
107+
return ASTHelpers.getType(binaryTree.getLeftOperand());
108+
}
109+
89110
// Need more information. Call again on parent.
90-
Tree parent = state.getPath().getParentPath().getParentPath().getLeaf();
91-
return getTargetType(original, parent, state);
111+
TreePath parentPath = path.getParentPath();
112+
Tree parent = parentPath.getLeaf();
113+
return getTargetType(tree, parent, state, parentPath);
92114
}
93115

94116
if (tree instanceof MethodInvocationTree) {
95117
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree;
96-
int index = methodInvocationTree.getArguments().indexOf(original);
118+
int index = methodInvocationTree.getArguments().indexOf(prev);
97119
return ASTHelpers.getSymbol(methodInvocationTree).params.get(index).type;
98120
}
99121

src/test/resources/tech/pegasys/tools/epchecks/MathTargetTypePositiveCases.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ public void expectedLongAllFuncs() {
8181
long l = Math.min(0, 1) * 1;
8282
}
8383

84+
public void binaryOperations() {
85+
// BUG: Diagnostic contains: Neither of the function arguments are long types
86+
long a = Math.min(0, 1) * 1;
87+
// BUG: Diagnostic contains: Neither of the function arguments are long types
88+
long b = Math.min(0, 1) * 1L;
89+
// BUG: Diagnostic contains: Neither of the function arguments are long types
90+
long c = 1 * Math.min(0, 1) * 1L;
91+
// BUG: Diagnostic contains: Neither of the function arguments are long types
92+
long d = 1 * 1 * 1 * 1 * Math.min(0, 1) * 1L;
93+
// BUG: Diagnostic contains: Neither of the function arguments are double types
94+
takesDouble(0, Math.min(1 / 2, Math.max(0, 1) - 1), 0);
95+
// BUG: Diagnostic contains: Neither of the function arguments are long types
96+
long e = Math.min(0, 1) & 27;
97+
// BUG: Diagnostic contains: Neither of the function arguments are long types
98+
long f = Math.min(0, 1) | 0x80;
99+
}
100+
84101
public void expectedLongVars() {
85102
int a = 0;
86103
int b = 1;
@@ -92,4 +109,11 @@ public void expectedLongArgs(int a, int b) {
92109
// BUG: Diagnostic contains: Neither of the function arguments are long types
93110
long c = Math.min(a, b);
94111
}
112+
113+
public void comparison(int a, int b) {
114+
// BUG: Diagnostic contains: Neither of the function arguments are long types
115+
boolean c = 27L == Math.min(a, b);
116+
// BUG: Diagnostic contains: Neither of the function arguments are long types
117+
boolean d = Math.min(a, b) == 27L;
118+
}
95119
}

0 commit comments

Comments
 (0)