Search in sources :

Example 56 with ExpressionTree

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

the class ReturnMissingNullable method matchReturn.

@Override
public Description matchReturn(ReturnTree tree, VisitorState state) {
    ExpressionTree returnExpression = tree.getExpression();
    if (returnExpression == null) {
        return Description.NO_MATCH;
    }
    // TODO(kmb): bail on more non-null expressions, such as "this", arithmethic, logical, and &&/||
    if (ASTHelpers.constValue(returnExpression) != null) {
        // This should include literals such as "true" or a string
        return Description.NO_MATCH;
    }
    JCMethodDecl method = findSurroundingMethod(state.getPath());
    if (method == null || isIgnoredReturnType(method, state)) {
        return Description.NO_MATCH;
    }
    if (TrustingNullnessAnalysis.hasNullableAnnotation(method.sym)) {
        return Description.NO_MATCH;
    }
    // Don't need dataflow to tell us that null is nullable
    if (returnExpression.getKind() == ExpressionTree.Kind.NULL_LITERAL) {
        return makeFix(method, tree, "Returning null literal");
    }
    // OK let's see what dataflow says
    Nullness nullness = TrustingNullnessAnalysis.instance(state.context).getNullness(new TreePath(state.getPath(), returnExpression), state.context);
    switch(nullness) {
        case BOTTOM:
        case NONNULL:
            return Description.NO_MATCH;
        case NULL:
            return makeFix(method, tree, "Definitely returning null");
        case NULLABLE:
            return makeFix(method, tree, "May return null");
        default:
            throw new AssertionError("Impossible: " + nullness);
    }
}
Also used : JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) TreePath(com.sun.source.util.TreePath) ExpressionTree(com.sun.source.tree.ExpressionTree) Nullness(com.google.errorprone.dataflow.nullnesspropagation.Nullness)

Example 57 with ExpressionTree

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

the class ProvidesNull method matchReturn.

/**
   * Matches explicit "return null" statements in methods annotated with {@code @Provides} but not
   * {@code @Nullable}.  Suggests either annotating the method with {@code @Nullable} or throwing a
   * {@link RuntimeException} instead.
   */
// TODO(eaftan): Use nullness dataflow analysis when it's ready
@Override
public Description matchReturn(ReturnTree returnTree, VisitorState state) {
    ExpressionTree returnExpression = returnTree.getExpression();
    if (returnExpression == null || returnExpression.getKind() != Kind.NULL_LITERAL) {
        return Description.NO_MATCH;
    }
    TreePath path = state.getPath();
    MethodTree enclosingMethod = null;
    while (true) {
        if (path == null || path.getLeaf() instanceof LambdaExpressionTree) {
            return Description.NO_MATCH;
        } else if (path.getLeaf() instanceof MethodTree) {
            enclosingMethod = (MethodTree) path.getLeaf();
            break;
        } else {
            path = path.getParentPath();
        }
    }
    MethodSymbol enclosingMethodSym = ASTHelpers.getSymbol(enclosingMethod);
    if (enclosingMethodSym == null) {
        return Description.NO_MATCH;
    }
    if (!ASTHelpers.hasAnnotation(enclosingMethodSym, "dagger.Provides", state) || ASTHelpers.hasDirectAnnotationWithSimpleName(enclosingMethodSym, "Nullable")) {
        return Description.NO_MATCH;
    }
    Fix addNullableFix = SuggestedFix.builder().prefixWith(enclosingMethod, "@Nullable\n").addImport("javax.annotation.Nullable").build();
    CatchTree enclosingCatch = ASTHelpers.findEnclosingNode(state.getPath(), CatchTree.class);
    if (enclosingCatch == null) {
        // If not in a catch block, suggest adding @Nullable first, then throwing an exception.
        Fix throwRuntimeExceptionFix = SuggestedFix.replace(returnTree, "throw new RuntimeException();");
        return buildDescription(returnTree).addFix(addNullableFix).addFix(throwRuntimeExceptionFix).build();
    } else {
        // If in a catch block, suggest throwing an exception first, then adding @Nullable.
        String replacement = String.format("throw new RuntimeException(%s);", enclosingCatch.getParameter().getName());
        Fix throwRuntimeExceptionFix = SuggestedFix.replace(returnTree, replacement);
        return buildDescription(returnTree).addFix(throwRuntimeExceptionFix).addFix(addNullableFix).build();
    }
}
Also used : LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) TreePath(com.sun.source.util.TreePath) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) MethodTree(com.sun.source.tree.MethodTree) CatchTree(com.sun.source.tree.CatchTree) ExpressionTree(com.sun.source.tree.ExpressionTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree)

Example 58 with ExpressionTree

use of com.sun.source.tree.ExpressionTree 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 = TreeInfo.skipParens((JCExpression) 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 : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) BinaryTree(com.sun.source.tree.BinaryTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 59 with ExpressionTree

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

the class DoubleCheckedLocking method findDCL.

/**
   * Matches an instance of DCL. The canonical pattern is:
   *
   * <pre>
   * {@code
   * if ($X == null) {
   *   synchronized (...) {
   *     if ($X == null) {
   *       ...
   *     }
   *     ...
   *   }
   * }
   * }
   * </pre>
   *
   * Gaps before the synchronized or inner 'if' statement are ignored, and the operands in the
   * null-checks are accepted in either order.
   */
@Nullable
static DCLInfo findDCL(IfTree outerIf) {
    // TODO(cushon): Optional.ifPresent...
    ExpressionTree outerIfTest = getNullCheckedExpression(outerIf.getCondition());
    if (outerIfTest == null) {
        return null;
    }
    SynchronizedTree synchTree = getChild(outerIf.getThenStatement(), SynchronizedTree.class);
    if (synchTree == null) {
        return null;
    }
    IfTree innerIf = getChild(synchTree.getBlock(), IfTree.class);
    if (innerIf == null) {
        return null;
    }
    ExpressionTree innerIfTest = getNullCheckedExpression(innerIf.getCondition());
    if (innerIfTest == null) {
        return null;
    }
    Symbol outerSym = ASTHelpers.getSymbol(outerIfTest);
    if (!Objects.equals(outerSym, ASTHelpers.getSymbol(innerIfTest))) {
        return null;
    }
    if (!(outerSym instanceof VarSymbol)) {
        return null;
    }
    VarSymbol var = (VarSymbol) outerSym;
    return DCLInfo.create(outerIf, synchTree, innerIf, var);
}
Also used : SynchronizedTree(com.sun.source.tree.SynchronizedTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) ExpressionTree(com.sun.source.tree.ExpressionTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) IfTree(com.sun.source.tree.IfTree) Nullable(javax.annotation.Nullable)

Example 60 with ExpressionTree

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

the class ProtoFieldNullComparison method getMethodName.

private static String getMethodName(ExpressionTree tree) {
    MethodInvocationTree method = (MethodInvocationTree) tree;
    ExpressionTree expressionTree = method.getMethodSelect();
    JCFieldAccess access = (JCFieldAccess) expressionTree;
    return access.sym.getQualifiedName().toString();
}
Also used : JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

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