Search in sources :

Example 71 with ExpressionTree

use of com.sun.source.tree.ExpressionTree in project error-prone by google.

the class InfiniteRecursion method matchMethod.

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
    if (tree.getBody() == null || tree.getBody().getStatements().size() != 1) {
        return NO_MATCH;
    }
    Tree statement = TreeInfo.skipParens((JCTree) Iterables.getOnlyElement(tree.getBody().getStatements()));
    ExpressionTree expr = statement.accept(new SimpleTreeVisitor<ExpressionTree, Void>() {

        @Override
        public ExpressionTree visitExpressionStatement(ExpressionStatementTree tree, Void unused) {
            return tree.getExpression();
        }

        @Override
        public ExpressionTree visitReturn(ReturnTree tree, Void unused) {
            return tree.getExpression();
        }
    }, null);
    if (!(expr instanceof MethodInvocationTree)) {
        return NO_MATCH;
    }
    ExpressionTree select = ((MethodInvocationTree) expr).getMethodSelect();
    switch(select.getKind()) {
        case IDENTIFIER:
            break;
        case MEMBER_SELECT:
            ExpressionTree receiver = ((MemberSelectTree) select).getExpression();
            if (receiver.getKind() != Kind.IDENTIFIER) {
                return NO_MATCH;
            }
            if (!((IdentifierTree) receiver).getName().contentEquals("this")) {
                return NO_MATCH;
            }
            break;
        default:
            return NO_MATCH;
    }
    MethodSymbol sym = ASTHelpers.getSymbol(tree);
    if (sym == null || !sym.equals(ASTHelpers.getSymbol(expr))) {
        return NO_MATCH;
    }
    return describeMatch(statement);
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ReturnTree(com.sun.source.tree.ReturnTree) MethodTree(com.sun.source.tree.MethodTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) JCTree(com.sun.tools.javac.tree.JCTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ReturnTree(com.sun.source.tree.ReturnTree)

Example 72 with ExpressionTree

use of com.sun.source.tree.ExpressionTree in project error-prone by google.

the class InvalidPatternSyntax method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState state) {
    if (!BAD_REGEX_USAGE.matches(methodInvocationTree, state)) {
        return Description.NO_MATCH;
    }
    // TODO: Suggest fixes for more situations.
    Description.Builder descriptionBuilder = buildDescription(methodInvocationTree);
    ExpressionTree arg = methodInvocationTree.getArguments().get(0);
    String value = (String) ((JCExpression) arg).type.constValue();
    String reasonInvalid = "";
    if (".".equals(value)) {
        descriptionBuilder.addFix(SuggestedFix.replace(arg, "\"\\\\.\""));
        reasonInvalid = "\".\" is a valid but useless regex";
    } else {
        try {
            Pattern.compile(value);
        } catch (PatternSyntaxException e) {
            reasonInvalid = e.getMessage();
        }
    }
    descriptionBuilder.setMessage(MESSAGE_BASE + reasonInvalid);
    return descriptionBuilder.build();
}
Also used : Description(com.google.errorprone.matchers.Description) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) ExpressionTree(com.sun.source.tree.ExpressionTree) PatternSyntaxException(java.util.regex.PatternSyntaxException)

Example 73 with ExpressionTree

use of com.sun.source.tree.ExpressionTree in project error-prone by google.

the class MockitoUsage method buildFix.

/**
   * Create fixes for invalid assertions.
   *
   * <ul>
   * <li>Rewrite `verify(mock.bar())` to `verify(mock).bar()`
   * <li>Rewrite `verify(mock.bar(), times(N))` to `verify(mock, times(N)).bar()`
   * <li>Rewrite `verify(mock, never())` to `verifyZeroInteractions(mock)`
   * <li>Finally, offer to delete the mock statement.
   * </ul>
   */
private void buildFix(Description.Builder builder, MethodInvocationTree tree, VisitorState state) {
    MethodInvocationTree mockitoCall = tree;
    List<? extends ExpressionTree> args = mockitoCall.getArguments();
    Tree mock = mockitoCall.getArguments().get(0);
    boolean isVerify = ASTHelpers.getSymbol(tree).getSimpleName().contentEquals("verify");
    if (isVerify && mock.getKind() == Kind.METHOD_INVOCATION) {
        MethodInvocationTree invocation = (MethodInvocationTree) mock;
        String verify = state.getSourceForNode(mockitoCall.getMethodSelect());
        String receiver = state.getSourceForNode(ASTHelpers.getReceiver(invocation));
        String mode = args.size() > 1 ? ", " + state.getSourceForNode(args.get(1)) : "";
        String call = state.getSourceForNode(invocation).substring(receiver.length());
        builder.addFix(SuggestedFix.replace(tree, String.format("%s(%s%s)%s", verify, receiver, mode, call)));
    }
    if (isVerify && args.size() > 1 && NEVER_METHOD.matches(args.get(1), state)) {
        // TODO(cushon): handle times(0) the same as never()
        builder.addFix(SuggestedFix.builder().addStaticImport("org.mockito.Mockito.verifyZeroInteractions").replace(tree, String.format("verifyZeroInteractions(%s)", mock)).build());
    }
    // Always suggest the naive semantics-preserving option, which is just to
    // delete the assertion:
    Tree parent = state.getPath().getParentPath().getLeaf();
    if (parent.getKind() == Kind.EXPRESSION_STATEMENT) {
        // delete entire expression statement
        builder.addFix(SuggestedFix.delete(parent));
    } else {
        builder.addFix(SuggestedFix.delete(tree));
    }
}
Also used : MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree)

Example 74 with ExpressionTree

use of com.sun.source.tree.ExpressionTree in project error-prone by google.

the class PreconditionsCheckNotNullPrimitive method describe.

/**
   * If the call to Preconditions.checkNotNull is part of an expression (assignment, return, etc.),
   * we substitute the argument for the method call. E.g.:
   * {@code bar = Preconditions.checkNotNull(foo); ==> bar = foo;}
   *
   * <p>If the argument to Preconditions.checkNotNull is a comparison using == or != and one of the
   * operands is null, we call checkNotNull on the non-null operand. E.g.:
   * {@code checkNotNull(a == null); ==> checkNotNull(a);}
   *
   * <p>If the argument is a method call or binary tree and its return type is boolean, change it to a
   * checkArgument/checkState. E.g.:
   * {@code Preconditions.checkNotNull(foo.hasFoo()) ==> Preconditions.checkArgument(foo.hasFoo())}
   *
   * <p>Otherwise, delete the checkNotNull call. E.g.:
   * {@code Preconditions.checkNotNull(foo); ==> [delete the line]}
   */
public Description describe(MethodInvocationTree methodInvocationTree, VisitorState state) {
    ExpressionTree arg1 = methodInvocationTree.getArguments().get(0);
    Tree parent = state.getPath().getParentPath().getLeaf();
    // Assignment, return, etc.
    if (parent.getKind() != Kind.EXPRESSION_STATEMENT) {
        return describeMatch(arg1, SuggestedFix.replace(methodInvocationTree, arg1.toString()));
    }
    // Comparison to null
    if (arg1.getKind() == Kind.EQUAL_TO || arg1.getKind() == Kind.NOT_EQUAL_TO) {
        BinaryTree binaryExpr = (BinaryTree) arg1;
        if (binaryExpr.getLeftOperand().getKind() == Kind.NULL_LITERAL) {
            return describeMatch(arg1, SuggestedFix.replace(arg1, binaryExpr.getRightOperand().toString()));
        }
        if (binaryExpr.getRightOperand().getKind() == Kind.NULL_LITERAL) {
            return describeMatch(arg1, SuggestedFix.replace(arg1, binaryExpr.getLeftOperand().toString()));
        }
    }
    if ((arg1 instanceof BinaryTree || arg1.getKind() == Kind.METHOD_INVOCATION || arg1.getKind() == Kind.LOGICAL_COMPLEMENT) && ((JCExpression) arg1).type == state.getSymtab().booleanType) {
        return describeMatch(arg1, createCheckArgumentOrStateCall(methodInvocationTree, state, arg1));
    }
    return describeMatch(arg1, SuggestedFix.delete(parent));
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) BinaryTree(com.sun.source.tree.BinaryTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 75 with ExpressionTree

use of com.sun.source.tree.ExpressionTree in project error-prone by google.

the class AbstractToString method checkToString.

/**
   * Tests if the given expression is converted to a String by its parent (i.e. its parent
   * is a string concat expression, {@code String.format}, or {@code println(Object)}).
   */
private Description checkToString(ExpressionTree tree, VisitorState state) {
    Symbol sym = ASTHelpers.getSymbol(tree);
    if (!(sym instanceof VarSymbol || sym instanceof MethodSymbol)) {
        return NO_MATCH;
    }
    Type type = ASTHelpers.getType(tree);
    if (type instanceof MethodType) {
        type = type.getReturnType();
    }
    Tree parent = state.getPath().getParentPath().getLeaf();
    ToStringKind toStringKind = isToString(parent, tree, state);
    if (toStringKind == ToStringKind.NONE) {
        return NO_MATCH;
    }
    Optional<Fix> fix;
    switch(toStringKind) {
        case IMPLICIT:
            fix = implicitToStringFix(tree, state);
            break;
        case EXPLICIT:
            fix = toStringFix(parent, tree, state);
            break;
        default:
            throw new AssertionError(toStringKind);
    }
    if (!typePredicate().apply(type, state)) {
        return NO_MATCH;
    }
    return maybeFix(tree, fix);
}
Also used : MethodType(com.sun.tools.javac.code.Type.MethodType) MethodType(com.sun.tools.javac.code.Type.MethodType) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Fix(com.google.errorprone.fixes.Fix) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Aggregations

ExpressionTree (com.sun.source.tree.ExpressionTree)78 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)27 Tree (com.sun.source.tree.Tree)18 Type (com.sun.tools.javac.code.Type)18 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)16 Symbol (com.sun.tools.javac.code.Symbol)14 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)14 JCTree (com.sun.tools.javac.tree.JCTree)14 Fix (com.google.errorprone.fixes.Fix)13 VariableTree (com.sun.source.tree.VariableTree)13 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)13 IdentifierTree (com.sun.source.tree.IdentifierTree)12 MemberSelectTree (com.sun.source.tree.MemberSelectTree)12 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)11 VisitorState (com.google.errorprone.VisitorState)9 AssignmentTree (com.sun.source.tree.AssignmentTree)9 BinaryTree (com.sun.source.tree.BinaryTree)9 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)8 MethodTree (com.sun.source.tree.MethodTree)8 TreePath (com.sun.source.util.TreePath)8