@Override
    public Void visitNewClass(NewClassTree tree, AnnotatedTypeMirror type) {
      boolean wrapperClass =
          TypesUtils.isBoxedPrimitive(type.getUnderlyingType())
              || TypesUtils.isDeclaredOfName(type.getUnderlyingType(), "java.lang.String");

      if (wrapperClass
          || (isUnderlyingTypeAValue(type)
              && methodIsStaticallyExecutable(TreeUtils.elementFromUse(tree)))) {
        // get arugment values
        List<? extends ExpressionTree> arguments = tree.getArguments();
        ArrayList<List<?>> argValues;
        if (arguments.size() > 0) {
          argValues = new ArrayList<List<?>>();
          for (ExpressionTree argument : arguments) {
            AnnotatedTypeMirror argType = getAnnotatedType(argument);
            List<?> values = getValues(argType, argType.getUnderlyingType());
            if (values.isEmpty()) {
              // values aren't known, so don't try to evaluate the
              // method
              return null;
            }
            argValues.add(values);
          }
        } else {
          argValues = null;
        }
        // Evaluate method
        List<?> returnValues =
            evalutator.evaluteConstrutorCall(argValues, tree, type.getUnderlyingType());
        AnnotationMirror returnType =
            resultAnnotationHandler(type.getUnderlyingType(), returnValues, tree);
        type.replaceAnnotation(returnType);
      }

      return null;
    }
  @Override
  public Void visitNewArray(NewArrayTree node, Void p) {
    AnnotatedArrayType type = atypeFactory.getAnnotatedType(node);
    AnnotatedTypeMirror componentType = type.getComponentType();
    if (componentType.hasEffectiveAnnotation(NONNULL)
        && !isNewArrayAllZeroDims(node)
        && !isNewArrayInToArray(node)
        && !TypesUtils.isPrimitive(componentType.getUnderlyingType())
        && checker.getLintOption("forbidnonnullarraycomponents", false)) {
      checker.report(
          Result.failure("new.array.type.invalid", componentType.getAnnotations(), type.toString()),
          node);
    }

    return super.visitNewArray(node, p);
  }
  /**
   * Determine the type of a field access (implicit or explicit) based on the receiver type and the
   * declared annotations for the field.
   *
   * @param type Type of the field access expression
   * @param declaredFieldAnnotations Annotations on the element.
   * @param receiverType Inferred annotations of the receiver
   */
  private void computeFieldAccessType(
      AnnotatedTypeMirror type,
      Collection<? extends AnnotationMirror> declaredFieldAnnotations,
      AnnotatedTypeMirror receiverType,
      AnnotatedTypeMirror fieldAnnotations,
      Element element) {
    // not necessary for primitive fields
    if (TypesUtils.isPrimitive(type.getUnderlyingType())) {
      return;
    }
    // not necessary if there is an explicit UnknownInitialization
    // annotation on the field
    if (AnnotationUtils.containsSameIgnoringValues(
        fieldAnnotations.getAnnotations(), UNCLASSIFIED)) {
      return;
    }
    if (isUnclassified(receiverType) || isFree(receiverType)) {

      TypeMirror fieldDeclarationType = element.getEnclosingElement().asType();
      boolean isInitializedForFrame = isInitializedForFrame(receiverType, fieldDeclarationType);
      if (isInitializedForFrame) {
        // The receiver is initialized for this frame.
        // Change the type of the field to @UnknownInitialization or @Raw so that
        // anything can be assigned to this field.
        type.replaceAnnotation(UNCLASSIFIED);
      } else if (computingAnnotatedTypeMirrorOfLHS) {
        // The receiver is not initialized for this frame, but the type of a lhs is being computed.
        // Change the type of the field to @UnknownInitialization or @Raw so that
        // anything can be assigned to this field.
        type.replaceAnnotation(UNCLASSIFIED);
      } else {
        // The receiver is not initialized for this frame and the type being computed is not a LHS.
        // Replace all annotations with the top annotation for that hierarchy.
        type.clearAnnotations();
        type.addAnnotations(qualHierarchy.getTopAnnotations());
      }

      if (!AnnotationUtils.containsSame(declaredFieldAnnotations, NOT_ONLY_COMMITTED) || !useFbc) {
        // add root annotation for all other hierarchies, and
        // Committed for the commitment hierarchy
        type.replaceAnnotation(COMMITTED);
      }
    }
  }
  /*
   * Provided that m is of a type that implements interface java.util.Map:
   * -Given a call m.containsKey(k), ensures that k is @KeyFor("m") in the thenStore of the transfer result.
   * -Given a call m.put(k, ...), ensures that k is @KeyFor("m") in the thenStore and elseStore of the transfer result.
   */
  @Override
  public TransferResult<CFValue, CFStore> visitMethodInvocation(
      MethodInvocationNode node, TransferInput<CFValue, CFStore> in) {

    TransferResult<CFValue, CFStore> result = super.visitMethodInvocation(node, in);

    String methodName = node.getTarget().getMethod().toString();

    // First verify if the method name is containsKey or put. This is an inexpensive check.

    boolean containsKey = methodName.startsWith("containsKey(");
    boolean put = methodName.startsWith("put(");

    if (containsKey || put) {
      // Now verify that the receiver of the method invocation is of a type
      // that extends that java.util.Map interface. This is a more expensive check.

      javax.lang.model.util.Types types = analysis.getTypes();

      TypeMirror mapInterfaceTypeMirror =
          types.erasure(
              TypesUtils.typeFromClass(types, analysis.getEnv().getElementUtils(), Map.class));

      TypeMirror receiverType = types.erasure(node.getTarget().getReceiver().getType());

      if (types.isSubtype(receiverType, mapInterfaceTypeMirror)) {

        FlowExpressionContext flowExprContext =
            FlowExpressionParseUtil.buildFlowExprContextForUse(node, checker);

        String mapName = flowExprContext.receiver.toString();
        Receiver keyReceiver = flowExprContext.arguments.get(0);

        KeyForAnnotatedTypeFactory atypeFactory =
            (KeyForAnnotatedTypeFactory) analysis.getTypeFactory();

        LinkedHashSet<String> keyForMaps = new LinkedHashSet<>();
        keyForMaps.add(mapName);

        final CFValue previousKeyValue = in.getValueOfSubNode(node.getArgument(0));
        if (previousKeyValue != null) {
          final AnnotationMirror prevAm =
              previousKeyValue.getType().getAnnotationInHierarchy(KEYFOR);
          if (prevAm != null && AnnotationUtils.areSameByClass(prevAm, KeyFor.class)) {
            keyForMaps.addAll(getKeys(prevAm));
          }
        }

        AnnotationMirror am = atypeFactory.createKeyForAnnotationMirrorWithValue(keyForMaps);

        if (containsKey) {
          ConditionalTransferResult<CFValue, CFStore> conditionalResult =
              (ConditionalTransferResult<CFValue, CFStore>) result;
          conditionalResult.getThenStore().insertValue(keyReceiver, am);
        } else if (put) {
          result.getThenStore().insertValue(keyReceiver, am);
          result.getElseStore().insertValue(keyReceiver, am);
        }
      }
    }

    return result;
  }