private void setNullnessForMapCalls()

in nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessPropagation.java [997:1045]


  private void setNullnessForMapCalls(
      MethodInvocationNode node,
      Symbol.MethodSymbol callee,
      List<Node> arguments,
      AccessPathNullnessPropagation.SubNodeValues inputs,
      AccessPathNullnessPropagation.Updates thenUpdates,
      AccessPathNullnessPropagation.Updates bothUpdates) {
    if (AccessPath.isContainsKey(callee, state)) {
      // make sure argument is a variable, and get its element
      AccessPath getAccessPath = AccessPath.getForMapInvocation(node, state, apContext);
      if (getAccessPath != null) {
        // in the then branch, we want the get() call with the same argument to be non-null
        // we assume that the declared target of the get() method will be in the same class
        // as containsKey()
        thenUpdates.set(getAccessPath, NONNULL);
      }
    } else if (AccessPath.isMapPut(callee, state)) {
      AccessPath getAccessPath = AccessPath.getForMapInvocation(node, state, apContext);
      if (getAccessPath != null) {
        Nullness value = inputs.valueOfSubNode(arguments.get(1));
        bothUpdates.set(getAccessPath, value);
      }
    } else if (AccessPath.isMapComputeIfAbsent(callee, state)) {
      AccessPath getAccessPath = AccessPath.getForMapInvocation(node, state, apContext);
      if (getAccessPath != null) {
        // TODO: For now, Function<K, V> implies a @NonNull V. We need to revisit this once we
        // support generics, but we do include a couple defensive tests below.
        if (arguments.size() < 2) {
          return;
        }
        Node funcNode = arguments.get(1);
        if (!funcNode.getType().getKind().equals(TypeKind.DECLARED)) {
          return;
        }
        Type.ClassType classType = (Type.ClassType) funcNode.getType();
        if (classType.getTypeArguments().size() != 2) {
          return;
        }
        Type functionReturnType = classType.getTypeArguments().get(1);
        // Unfortunately, functionReturnType.tsym seems to elide annotation info, so we can't call
        // the Nullness.* methods that deal with Symbol. We might have better APIs for this kind of
        // check once we have real generics support.
        if (!Nullness.hasNullableAnnotation(
            functionReturnType.getAnnotationMirrors().stream(), config)) {
          bothUpdates.set(getAccessPath, NONNULL);
        }
      }
    }
  }