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();
}
}
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;
}
Aggregations