Search in sources :

Example 21 with BinaryTree

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();
}
Also used : MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) BinaryTree(com.sun.source.tree.BinaryTree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BinaryTree(com.sun.source.tree.BinaryTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree)

Example 22 with BinaryTree

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));
    }
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) BinaryTree(com.sun.source.tree.BinaryTree) JCTree(com.sun.tools.javac.tree.JCTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 23 with BinaryTree

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;
}
Also used : BinaryTree(com.sun.source.tree.BinaryTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 24 with BinaryTree

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;
    }
}
Also used : Types(com.sun.tools.javac.code.Types) SimpleTreeVisitor(com.sun.source.util.SimpleTreeVisitor) ClassTree(com.sun.source.tree.ClassTree) BinaryTree(com.sun.source.tree.BinaryTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ReturnTree(com.sun.source.tree.ReturnTree) Symtab(com.sun.tools.javac.code.Symtab) Type(com.sun.tools.javac.code.Type) VisitorState(com.google.errorprone.VisitorState) ReturnTree(com.sun.source.tree.ReturnTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 25 with BinaryTree

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();
}
Also used : ASTHelpers.getType(com.google.errorprone.util.ASTHelpers.getType) ASTHelpers.isSameType(com.google.errorprone.util.ASTHelpers.isSameType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) BinaryTree(com.sun.source.tree.BinaryTree) VariableTree(com.sun.source.tree.VariableTree) LiteralTree(com.sun.source.tree.LiteralTree) BinaryTree(com.sun.source.tree.BinaryTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeCastTree(com.sun.source.tree.TypeCastTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) LiteralTree(com.sun.source.tree.LiteralTree)

Aggregations

BinaryTree (com.sun.source.tree.BinaryTree)30 ExpressionTree (com.sun.source.tree.ExpressionTree)26 Tree (com.sun.source.tree.Tree)17 LiteralTree (com.sun.source.tree.LiteralTree)15 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)13 IdentifierTree (com.sun.source.tree.IdentifierTree)11 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)11 MemberSelectTree (com.sun.source.tree.MemberSelectTree)10 ClassTree (com.sun.source.tree.ClassTree)9 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)9 TypeCastTree (com.sun.source.tree.TypeCastTree)9 MethodTree (com.sun.source.tree.MethodTree)8 PrimitiveTypeTree (com.sun.source.tree.PrimitiveTypeTree)8 VariableTree (com.sun.source.tree.VariableTree)8 AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)6 BlockTree (com.sun.source.tree.BlockTree)6 ReturnTree (com.sun.source.tree.ReturnTree)6 StatementTree (com.sun.source.tree.StatementTree)6 TypeMirror (javax.lang.model.type.TypeMirror)6 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)5