1515import static com .google .errorprone .BugPattern .SeverityLevel .WARNING ;
1616import static com .google .errorprone .matchers .Matchers .staticMethod ;
1717
18+ import java .util .List ;
1819import javax .lang .model .type .TypeKind ;
1920
2021import com .google .auto .service .AutoService ;
3435import com .sun .source .tree .Tree ;
3536import com .sun .source .tree .TypeCastTree ;
3637import com .sun .source .tree .VariableTree ;
38+ import com .sun .source .util .TreePath ;
3739import 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
0 commit comments