private Description checkCastToNonNullTakesNullable()

in nullaway/src/main/java/com/uber/nullaway/NullAway.java [2038:2093]


  private Description checkCastToNonNullTakesNullable(
      Tree tree,
      VisitorState state,
      Symbol.MethodSymbol methodSymbol,
      List<? extends ExpressionTree> actualParams) {
    String qualifiedName =
        ASTHelpers.enclosingClass(methodSymbol) + "." + methodSymbol.getSimpleName().toString();
    Integer castToNonNullPosition;
    if (qualifiedName.equals(config.getCastToNonNullMethod())
        && methodSymbol.getParameters().size() == 1) {
      // castToNonNull method passed to CLI config, it acts as a cast-to-non-null on its first
      // argument. Since this is a single argument method, we skip further querying of handlers.
      castToNonNullPosition = 0;
    } else {
      castToNonNullPosition =
          handler.castToNonNullArgumentPositionsForMethod(
              actualParams, null, new MethodAnalysisContext(this, state, methodSymbol));
    }
    if (castToNonNullPosition != null) {
      ExpressionTree actual = actualParams.get(castToNonNullPosition);
      TreePath enclosingMethodOrLambda =
          NullabilityUtil.findEnclosingMethodOrLambdaOrInitializer(state.getPath());
      boolean isInitializer;
      if (enclosingMethodOrLambda == null) {
        throw new RuntimeException("no enclosing method, lambda or initializer!");
      } else if (enclosingMethodOrLambda.getLeaf() instanceof LambdaExpressionTree) {
        isInitializer = false;
      } else if (enclosingMethodOrLambda.getLeaf() instanceof MethodTree) {
        MethodTree enclosingMethod = (MethodTree) enclosingMethodOrLambda.getLeaf();
        isInitializer = isInitializerMethod(state, ASTHelpers.getSymbol(enclosingMethod));
      } else {
        // Initializer block
        isInitializer = true;
      }
      if (!isInitializer && !mayBeNullExpr(state, actual)) {
        String message =
            "passing known @NonNull parameter '"
                + state.getSourceForNode(actual)
                + "' to CastToNonNullMethod ("
                + qualifiedName
                + ") at position "
                + castToNonNullPosition
                + ". This method argument should only take values that NullAway considers @Nullable "
                + "at the invocation site, but which are known not to be null at runtime.";
        return errorBuilder.createErrorDescription(
            new ErrorMessage(MessageTypes.CAST_TO_NONNULL_ARG_NONNULL, message),
            // The Tree passed as suggestTree is the expression being cast
            // to avoid recomputing the arg index:
            actual,
            buildDescription(tree),
            state,
            null);
      }
    }
    return Description.NO_MATCH;
  }