Search in sources :

Example 21 with LambdaExpressionTree

use of com.sun.source.tree.LambdaExpressionTree 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) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) 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 22 with LambdaExpressionTree

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

the class FutureReturnValueIgnored method matchReturn.

/**
 * Returning a type of Future from a lambda or method that returns Object loses the Future type,
 * which can result in suppressed errors or race conditions.
 */
@Override
public Description matchReturn(ReturnTree tree, VisitorState state) {
    Type objectType = Objects.requireNonNull(state.getTypeFromString("java.lang.Object"));
    Type futureType = Objects.requireNonNull(state.getTypeFromString("java.util.concurrent.Future"));
    Type resultType = ASTHelpers.getResultType(tree.getExpression());
    if (resultType == null) {
        return Description.NO_MATCH;
    }
    if (resultType.getKind() == TypeKind.NULL || resultType.getKind() == TypeKind.NONE) {
        return Description.NO_MATCH;
    }
    if (ASTHelpers.isSubtype(resultType, futureType, state)) {
        // Traverse enclosing nodes of this return tree until either a lambda or a Method is reached.
        for (Tree enclosing : state.getPath()) {
            if (enclosing instanceof MethodTree) {
                MethodTree methodTree = (MethodTree) enclosing;
                MethodSymbol symbol = ASTHelpers.getSymbol(methodTree);
                if (ASTHelpers.isSubtype(objectType, symbol.getReturnType(), state) && !isWhitelistedInterfaceMethod(symbol, state)) {
                    return buildDescription(tree).setMessage(String.format("Returning %s from method that returns %s. Errors from the returned future" + " may be ignored.", resultType, symbol.getReturnType())).build();
                } else {
                    break;
                }
            }
            if (enclosing instanceof LambdaExpressionTree) {
                LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclosing;
                if (isObjectReturningLambdaExpression(lambdaTree, state)) {
                    return buildDescription(tree).setMessage(String.format("Returning %s from method that returns Object. Errors from the returned" + " future will be ignored.", resultType)).build();
                } else {
                    break;
                }
            }
        }
    }
    return Description.NO_MATCH;
}
Also used : LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ReturnTree(com.sun.source.tree.ReturnTree) MethodTree(com.sun.source.tree.MethodTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree)

Aggregations

LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)22 MethodTree (com.sun.source.tree.MethodTree)19 VariableTree (com.sun.source.tree.VariableTree)15 ExpressionTree (com.sun.source.tree.ExpressionTree)14 Tree (com.sun.source.tree.Tree)13 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)12 NewClassTree (com.sun.source.tree.NewClassTree)11 ClassTree (com.sun.source.tree.ClassTree)10 ReturnTree (com.sun.source.tree.ReturnTree)9 AssignmentTree (com.sun.source.tree.AssignmentTree)8 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)7 AnnotationTree (com.sun.source.tree.AnnotationTree)6 MemberReferenceTree (com.sun.source.tree.MemberReferenceTree)6 MemberSelectTree (com.sun.source.tree.MemberSelectTree)6 AnnotatedExecutableType (org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType)6 TreePath (com.sun.source.util.TreePath)5 CFGMethod (org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod)5 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)4 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)4 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)4