use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class AbstractReferenceEquality method inOrStatementWithEqualsCheck.
private static Optional<Fix> inOrStatementWithEqualsCheck(VisitorState state, BinaryTree tree) {
// Only attempt to handle a == b || a.equals(b);
if (tree.getKind() == Kind.NOT_EQUAL_TO) {
return Optional.empty();
}
ExpressionTree lhs = tree.getLeftOperand();
ExpressionTree rhs = tree.getRightOperand();
Tree parent = state.getPath().getParentPath().getLeaf();
if (parent.getKind() != Kind.CONDITIONAL_OR) {
return Optional.empty();
}
BinaryTree p = (BinaryTree) parent;
if (p.getLeftOperand() != tree) {
// a == b is on the RHS, ignore this construction
return Optional.empty();
}
// If the other half of this or statement is foo.equals(bar) or Objects.equals(foo, bar)
// replace the or statement with the other half as already written.
ExpressionTree otherExpression = ASTHelpers.stripParentheses(p.getRightOperand());
if (!(otherExpression instanceof MethodInvocationTree)) {
return Optional.empty();
}
MethodInvocationTree other = (MethodInvocationTree) otherExpression;
// a == b || Objects.equals(a, b) => Objects.equals(a, b)
if (EQUALS_STATIC_METHODS.matches(otherExpression, state)) {
List<? extends ExpressionTree> arguments = other.getArguments();
if (treesMatch(arguments.get(0), arguments.get(1), lhs, rhs)) {
return Optional.of(SuggestedFix.replace(parent, state.getSourceForNode(otherExpression)));
}
}
// a == b || a.equals(b) => a.equals(b)
if (OBJECT_INSTANCE_EQUALS.matches(otherExpression, state)) {
if (treesMatch(ASTHelpers.getReceiver(other), other.getArguments().get(0), lhs, rhs)) {
return Optional.of(SuggestedFix.replace(parent, state.getSourceForNode(otherExpression)));
}
}
return Optional.empty();
}
use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class UseCorrectAssertInTests method suggestFixForSameReference.
/**
* Handles the case "expr1 == expr2"
*/
private static void suggestFixForSameReference(SuggestedFix.Builder fix, AssertTree foundAssert, VisitorState state, boolean isEqual) {
BinaryTree equalityTree = (BinaryTree) TreeInfo.skipParens((JCTree) foundAssert.getCondition());
ExpressionTree expr1 = equalityTree.getLeftOperand();
ExpressionTree expr2 = equalityTree.getRightOperand();
if (expr1.getKind() == NULL_LITERAL) {
// case: "assert null [op] expr"
addFix(fix, (JCExpression) expr2, foundAssert, state, isEqual ? IS_NULL : IS_NOT_NULL);
} else if (expr2.getKind() == NULL_LITERAL) {
// case: "assert expr [op] null"
addFix(fix, (JCExpression) expr1, foundAssert, state, isEqual ? IS_NULL : IS_NOT_NULL);
} else {
// case: "assert expr1 [op] expr2"
addFix(fix, (JCExpression) expr1, foundAssert, state, String.format(isEqual ? IS_SAME_AS : IS_NOT_SAME_AS, expr2));
}
}
use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class DoubleCheckedLocking method getNullCheckedExpression.
/**
* Matches comparisons to null (e.g. {@code foo == null}) and returns the expression being tested.
*/
private static ExpressionTree getNullCheckedExpression(ExpressionTree condition) {
condition = stripParentheses(condition);
if (!(condition instanceof BinaryTree)) {
return null;
}
BinaryTree bin = (BinaryTree) condition;
ExpressionTree other;
if (bin.getLeftOperand().getKind() == Kind.NULL_LITERAL) {
other = bin.getRightOperand();
} else if (bin.getRightOperand().getKind() == Kind.NULL_LITERAL) {
other = bin.getLeftOperand();
} else {
return null;
}
return other;
}
use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class ComparisonContractViolated method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (tree.getBody() == null) {
return Description.NO_MATCH;
}
// Test that the match is in a Comparable.compareTo or Comparator.compare method.
ClassTree declaringClass = ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class);
if (!COMPARABLE_CLASS_MATCHER.matches(declaringClass, state) && !COMPARATOR_CLASS_MATCHER.matches(declaringClass, state)) {
return Description.NO_MATCH;
}
if (!COMPARABLE_METHOD_MATCHER.matches(tree, state) && !COMPARATOR_METHOD_MATCHER.matches(tree, state)) {
return Description.NO_MATCH;
}
final Set<ComparisonResult> seenResults = EnumSet.noneOf(ComparisonResult.class);
final TreeVisitor<Void, VisitorState> visitReturnExpression = new SimpleTreeVisitor<Void, VisitorState>() {
@Override
protected Void defaultAction(Tree node, VisitorState state) {
seenResults.add(node.accept(CONSTANT_VISITOR, state));
return null;
}
@Override
public Void visitConditionalExpression(ConditionalExpressionTree node, VisitorState state) {
node.getTrueExpression().accept(this, state);
node.getFalseExpression().accept(this, state);
return null;
}
};
tree.getBody().accept(new TreeScanner<Void, VisitorState>() {
@Override
public Void visitReturn(ReturnTree node, VisitorState state) {
return node.getExpression().accept(visitReturnExpression, state);
}
}, state);
if (seenResults.isEmpty() || seenResults.contains(ComparisonResult.NONCONSTANT)) {
return Description.NO_MATCH;
}
if (!seenResults.contains(ComparisonResult.ZERO)) {
if (tree.getBody().getStatements().size() == 1 && tree.getBody().getStatements().get(0).getKind() == Kind.RETURN) {
ReturnTree returnTree = (ReturnTree) tree.getBody().getStatements().get(0);
if (returnTree.getExpression().getKind() == Kind.CONDITIONAL_EXPRESSION) {
ConditionalExpressionTree condTree = (ConditionalExpressionTree) returnTree.getExpression();
ExpressionTree conditionExpr = condTree.getCondition();
conditionExpr = ASTHelpers.stripParentheses(conditionExpr);
if (!(conditionExpr instanceof BinaryTree)) {
return describeMatch(tree);
}
ComparisonResult trueConst = condTree.getTrueExpression().accept(CONSTANT_VISITOR, state);
ComparisonResult falseConst = condTree.getFalseExpression().accept(CONSTANT_VISITOR, state);
boolean trueFirst;
if (trueConst == ComparisonResult.NEGATIVE_CONSTANT && falseConst == ComparisonResult.POSITIVE_CONSTANT) {
trueFirst = true;
} else if (trueConst == ComparisonResult.POSITIVE_CONSTANT && falseConst == ComparisonResult.NEGATIVE_CONSTANT) {
trueFirst = false;
} else {
return describeMatch(tree);
}
switch(conditionExpr.getKind()) {
case LESS_THAN:
case LESS_THAN_EQUAL:
break;
case GREATER_THAN:
case GREATER_THAN_EQUAL:
trueFirst = !trueFirst;
break;
default:
return describeMatch(tree);
}
BinaryTree binaryExpr = (BinaryTree) conditionExpr;
Type ty = ASTHelpers.getType(binaryExpr.getLeftOperand());
Types types = Types.instance(state.context);
Symtab symtab = Symtab.instance(state.context);
ExpressionTree first = trueFirst ? binaryExpr.getLeftOperand() : binaryExpr.getRightOperand();
ExpressionTree second = trueFirst ? binaryExpr.getRightOperand() : binaryExpr.getLeftOperand();
String compareType;
if (types.isSameType(ty, symtab.intType)) {
compareType = "Integer";
} else if (types.isSameType(ty, symtab.longType)) {
compareType = "Long";
} else {
return describeMatch(tree);
}
return describeMatch(condTree, SuggestedFix.replace(condTree, String.format("%s.compare(%s, %s)", compareType, state.getSourceForNode(first), state.getSourceForNode(second))));
}
}
return describeMatch(tree);
}
if (COMPARATOR_METHOD_MATCHER.matches(tree, state) && (seenResults.contains(ComparisonResult.NEGATIVE_CONSTANT) != seenResults.contains(ComparisonResult.POSITIVE_CONSTANT))) {
// See e.g. com.google.common.collect.Cut.BelowAll.
return describeMatch(tree);
} else {
return Description.NO_MATCH;
}
}
use of com.sun.source.tree.BinaryTree in project error-prone by google.
the class ConstantOverflow method longFix.
/**
* If the left operand of an int binary expression is an int literal, suggest making it a long.
*/
private Fix longFix(ExpressionTree expr, VisitorState state) {
BinaryTree binExpr = null;
while (expr instanceof BinaryTree) {
binExpr = (BinaryTree) expr;
expr = binExpr.getLeftOperand();
}
if (!(expr instanceof LiteralTree) || expr.getKind() != Kind.INT_LITERAL) {
return null;
}
Type intType = state.getSymtab().intType;
if (!isSameType(getType(binExpr), intType, state)) {
return null;
}
SuggestedFix.Builder fix = SuggestedFix.builder().postfixWith(expr, "L");
Tree parent = state.getPath().getParentPath().getLeaf();
if (parent instanceof VariableTree && isSameType(getType(parent), intType, state)) {
fix.replace(((VariableTree) parent).getType(), "long");
}
return fix.build();
}
Aggregations