public void compareGenericTypeParameterNullabilityForCall()

in nullaway/src/main/java/com/uber/nullaway/generics/GenericsChecks.java [1557:1655]


  public void compareGenericTypeParameterNullabilityForCall(
      Symbol.MethodSymbol methodSymbol, Tree tree, VisitorState state) {
    Config config = analysis.getConfig();
    if (!config.isJSpecifyMode()) {
      return;
    }
    Type invokedMethodType = methodSymbol.type;
    Type enclosingType = null;
    if (tree instanceof NewClassTree newClassTree) {
      if (hasInferredClassTypeArguments(newClassTree)) {
        TreePath currentPath = state.getPath();
        if (currentPath != null && ASTHelpers.stripParentheses(currentPath.getLeaf()) == tree) {
          TreePath parentPath = currentPath.getParentPath();
          if (parentPath != null) {
            enclosingType = getDiamondTypeFromParentContext(newClassTree, state, parentPath);
          }
        }
      }
    }
    if (enclosingType == null) {
      enclosingType = getEnclosingTypeForCallExpression(methodSymbol, tree, null, state, false);
    }
    if (enclosingType != null) {
      invokedMethodType =
          TypeSubstitutionUtils.memberType(state.getTypes(), enclosingType, methodSymbol, config);
    }

    // substitute type arguments for generic methods with explicit type arguments
    if (tree instanceof MethodInvocationTree && invokedMethodType instanceof Type.ForAll) {
      invokedMethodType =
          substituteTypeArgsInGenericMethodType(
              tree, (Type.ForAll) invokedMethodType, null, state, false);
    }

    Type.MethodType finalMethodType =
        handler.onOverrideMethodType(methodSymbol, invokedMethodType.asMethodType(), state);
    new InvocationArguments(tree, finalMethodType)
        .forEach(
            (currentActualParam, argPos, formalParameter, unused) -> {
              if (formalParameter.isRaw()) {
                // bail out of any checking involving raw types for now
                return;
              }

              if (currentActualParam instanceof MemberReferenceTree memberReferenceTree) {
                // the type of the method reference tree provided by javac may not capture
                // nullability of nested types. So, do explicit type checks based on the return and
                // parameter types of the referenced method
                GenericsUtils.processMethodRefTypeRelations(
                    this,
                    formalParameter,
                    memberReferenceTree,
                    state,
                    (subtype, supertype, relationKind) -> {
                      if (!subtypeParameterNullability(supertype, subtype, state)) {
                        if (relationKind == MethodRefTypeRelationKind.RETURN) {
                          reportInvalidMethodReferenceReturnTypeError(
                              memberReferenceTree, supertype, subtype, state);
                        } else {
                          reportInvalidMethodReferenceParameterTypeError(
                              memberReferenceTree, subtype, supertype, state);
                        }
                      }
                    });
                return;
              }

              Type actualParameterType = null;
              if (currentActualParam instanceof LambdaExpressionTree) {
                maybeStorePolyExpressionTypeFromTarget(currentActualParam, formalParameter);
              }
              Type inferredPolyType = inferredPolyExpressionTypes.get(currentActualParam);
              if (inferredPolyType != null) {
                actualParameterType = inferredPolyType;
              } else {
                TreePath pathToActualParam = new TreePath(state.getPath(), currentActualParam);
                actualParameterType =
                    getTreeType(currentActualParam, state.withPath(pathToActualParam));
              }
              if (actualParameterType != null) {
                if (isGenericCallNeedingInference(currentActualParam)) {
                  // infer the type of the method call based on the assignment context
                  // and the formal parameter type
                  actualParameterType =
                      inferGenericMethodCallType(
                          state,
                          (MethodInvocationTree) currentActualParam,
                          null,
                          formalParameter,
                          false,
                          false);
                }
                if (!subtypeParameterNullability(formalParameter, actualParameterType, state)) {
                  reportInvalidParametersNullabilityError(
                      formalParameter, actualParameterType, currentActualParam, state);
                }
              }
            });
  }