private static NullnessStore lambdaInitialStore()

in nullaway/src/main/java/com/uber/nullaway/dataflow/CoreNullnessStoreInitializer.java [85:156]


  private static NullnessStore lambdaInitialStore(
      UnderlyingAST.CFGLambda underlyingAST,
      List<LocalVariableNode> parameters,
      Handler handler,
      Context context,
      Types types,
      Config config,
      CodeAnnotationInfo codeAnnotationInfo) {
    // include nullness info for locals from enclosing environment
    EnclosingEnvironmentNullness environmentNullness =
        EnclosingEnvironmentNullness.instance(context);
    NullnessStore environmentMapping =
        Objects.requireNonNull(
            environmentNullness.getEnvironmentMapping(underlyingAST.getLambdaTree()),
            "no environment stored for lambda");
    NullnessStore.Builder result = environmentMapping.toBuilder();
    LambdaExpressionTree code = underlyingAST.getLambdaTree();
    // need to check annotation for i'th parameter of functional interface declaration
    Symbol.MethodSymbol fiMethodSymbol = NullabilityUtil.getFunctionalInterfaceMethod(code, types);
    com.sun.tools.javac.util.List<Symbol.VarSymbol> fiMethodParameters =
        fiMethodSymbol.getParameters();
    // This obtains the types of the functional interface method parameters with preserved
    // annotations in case of generic type arguments.  Only used in JSpecify mode.
    List<Type> overridenMethodParamTypeList =
        TypeSubstitutionUtils.memberType(
                types, castToNonNull(ASTHelpers.getType(code)), fiMethodSymbol, config)
            .getParameterTypes();
    // If fiArgumentPositionNullness[i] == null, parameter position i is unannotated
    @Nullable Nullness[] fiArgumentPositionNullness = new Nullness[fiMethodParameters.size()];
    boolean isFIAnnotated =
        !codeAnnotationInfo.isSymbolUnannotated(fiMethodSymbol, config, handler);
    if (isFIAnnotated) {
      for (int i = 0; i < fiMethodParameters.size(); i++) {
        if (Nullness.hasNullableAnnotation(fiMethodParameters.get(i), config)) {
          // Get the Nullness if the Annotation is directly written with the parameter
          fiArgumentPositionNullness[i] = NULLABLE;
        } else if (config.isJSpecifyMode()
            && Nullness.hasNullableAnnotation(
                overridenMethodParamTypeList.get(i).getAnnotationMirrors().stream(), config)) {
          // Get the Nullness if the Annotation is indirectly applied through a generic type if we
          // are in JSpecify mode
          fiArgumentPositionNullness[i] = NULLABLE;
        } else {
          fiArgumentPositionNullness[i] = NONNULL;
        }
      }
    }
    fiArgumentPositionNullness =
        handler.onOverrideMethodInvocationParametersNullability(
            context, fiMethodSymbol, isFIAnnotated, fiArgumentPositionNullness);

    for (int i = 0; i < parameters.size(); i++) {
      LocalVariableNode param = parameters.get(i);
      VariableTree variableTree = code.getParameters().get(i);
      Element element = param.getElement();
      Nullness assumed;
      // we treat lambda parameters differently; they "inherit" the nullability of the
      // corresponding functional interface parameter, unless they are explicitly annotated
      if (Nullness.hasNullableAnnotation((Symbol) element, config)) {
        assumed = NULLABLE;
      } else if (!NullabilityUtil.lambdaParamIsImplicitlyTyped(variableTree)) {
        // the parameter has a declared type with no @Nullable annotation
        // treat as non-null
        assumed = NONNULL;
      } else {
        assumed = fiArgumentPositionNullness[i] == null ? NONNULL : fiArgumentPositionNullness[i];
      }
      result.setInformation(AccessPath.fromLocal(param), assumed);
    }
    result = handler.onDataflowInitialStore(underlyingAST, parameters, result);
    return result.build();
  }