in nullaway/src/main/java/com/uber/nullaway/NullAway.java [969:1020]
private Description checkReturnExpression(
ExpressionTree retExpr,
Symbol.MethodSymbol methodSymbol,
@Nullable LambdaExpressionTree lambdaTree,
Tree errorTree,
VisitorState state) {
Type returnType = methodSymbol.getReturnType();
if (returnType.isPrimitive()) {
// check for unboxing
doUnboxingCheck(state, retExpr);
return Description.NO_MATCH;
}
if (ASTHelpers.isSameType(returnType, Suppliers.JAVA_LANG_VOID_TYPE.get(state), state)) {
// Temporarily treat a Void return type as if it were @Nullable Void. Change this once
// we are confident that all use cases can be type checked reasonably (may require generics
// support)
return Description.NO_MATCH;
}
// Check generic type arguments for returned expression here, since we need to check the type
// arguments regardless of the top-level nullability of the return type
GenericsChecks.checkTypeParameterNullnessForFunctionReturnType(
retExpr, methodSymbol, this, state);
// Now, perform the check for returning @Nullable from @NonNull. First, we check if the return
// type is @Nullable, and if so, bail out.
if (getMethodReturnNullness(methodSymbol, state, Nullness.NULLABLE).equals(Nullness.NULLABLE)) {
return Description.NO_MATCH;
} else if (config.isJSpecifyMode() && lambdaTree != null) {
if (GenericsChecks.getGenericMethodReturnTypeNullness(
methodSymbol, ASTHelpers.getType(lambdaTree), state, config)
.equals(Nullness.NULLABLE)
|| GenericsChecks.passingLambdaOrMethodRefWithGenericReturnToUnmarkedCode(
methodSymbol, lambdaTree, state, config, codeAnnotationInfo, handler)) {
// In JSpecify mode, the return type of a lambda may be @Nullable via a type argument
return Description.NO_MATCH;
}
}
// Return type is @NonNull. Check if the expression is @Nullable
if (mayBeNullExpr(state, retExpr)) {
return errorBuilder.createErrorDescriptionForNullAssignment(
new ErrorMessage(
MessageTypes.RETURN_NULLABLE,
"returning @Nullable expression from method with @NonNull return type"),
retExpr,
buildDescription(errorTree),
state,
methodSymbol);
}
return Description.NO_MATCH;
}