@Override
 public Void visitTypeCast(TypeCastTree tree, AnnotatedTypeMirror type) {
   if (isUnderlyingTypeAValue(type)) {
     AnnotatedTypeMirror castedAnnotation = getAnnotatedType(tree.getExpression());
     List<?> values = getValues(castedAnnotation, type.getUnderlyingType());
     type.replaceAnnotation(resultAnnotationHandler(type.getUnderlyingType(), values, tree));
   } else if (type.getKind() == TypeKind.ARRAY) {
     if (tree.getExpression().getKind() == Kind.NULL_LITERAL) {
       type.replaceAnnotation(BOTTOMVAL);
     }
   }
   return null;
 }
    @Override
    public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) {

      List<? extends ExpressionTree> dimensions = tree.getDimensions();
      List<? extends ExpressionTree> initializers = tree.getInitializers();

      // Dimensions provided
      if (!dimensions.isEmpty()) {
        handleDimensions(dimensions, (AnnotatedArrayType) type);
      } else {
        // Initializer used
        handleInitalizers(initializers, (AnnotatedArrayType) type);

        AnnotationMirror newQual;
        Class<?> clazz = ValueCheckerUtils.getClassFromType(type.getUnderlyingType());
        String stringVal = null;
        if (clazz.equals(byte[].class)) {
          stringVal = getByteArrayStringVal(initializers);
        } else if (clazz.equals(char[].class)) {
          stringVal = getCharArrayStringVal(initializers);
        }

        if (stringVal != null) {
          newQual = createStringAnnotation(Collections.singletonList(stringVal));
          type.replaceAnnotation(newQual);
        }
      }

      return null;
    }
  /**
   * 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);
      }
    }
  }
    /**
     * If any constant-value annotation has &gt; MAX_VALUES number of values provided, treats the
     * value as UnknownVal. Works together with ValueVisitor.visitAnnotation, which issues a warning
     * to the user in this case.
     */
    private void replaceWithUnknownValIfTooManyValues(AnnotatedTypeMirror atm) {
      AnnotationMirror anno = atm.getAnnotationInHierarchy(UNKNOWNVAL);

      if (anno != null && anno.getElementValues().size() > 0) {
        List<Object> values =
            AnnotationUtils.getElementValueArray(anno, "value", Object.class, false);
        if (values != null && values.size() > MAX_VALUES) {
          atm.replaceAnnotation(UNKNOWNVAL);
        }
      }
    }
    @Override
    public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) {
      if (TreeUtils.isFieldAccess(tree) && isUnderlyingTypeAValue(type)) {
        VariableElement elem = (VariableElement) InternalUtils.symbol(tree);
        Object value = elem.getConstantValue();
        if (value != null) {
          // compile time constant
          type.replaceAnnotation(
              resultAnnotationHandler(
                  type.getUnderlyingType(), Collections.singletonList(value), tree));
          return null;
        }
        if (ElementUtils.isStatic(elem) && ElementUtils.isFinal(elem)) {
          Element e = InternalUtils.symbol(tree.getExpression());
          if (e != null) {
            String classname = ElementUtils.getQualifiedClassName(e).toString();
            String fieldName = tree.getIdentifier().toString();
            value = evalutator.evaluateStaticFieldAccess(classname, fieldName, tree);
            if (value != null)
              type.replaceAnnotation(
                  resultAnnotationHandler(
                      type.getUnderlyingType(), Collections.singletonList(value), tree));
            return null;
          }
        }

        if (tree.getIdentifier().toString().equals("length")) {
          AnnotatedTypeMirror receiverType = getAnnotatedType(tree.getExpression());
          if (receiverType.getKind() == TypeKind.ARRAY) {
            AnnotationMirror arrayAnno = receiverType.getAnnotation(ArrayLen.class);
            if (arrayAnno != null) {
              // array.length, where array : @ArrayLen(x)
              List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno);
              type.replaceAnnotation(createNumberAnnotationMirror(new ArrayList<Number>(lengths)));
              return null;
            }
          }
        }
      }
      return null;
    }
 public void handle(MethodInvocationTree tree, AnnotatedExecutableType method) {
   if (TreeUtils.isMethodInvocation(tree, systemGetProperty, env)) {
     List<? extends ExpressionTree> args = tree.getArguments();
     assert args.size() == 1;
     ExpressionTree arg = args.get(0);
     if (arg.getKind() == Tree.Kind.STRING_LITERAL) {
       String literal = (String) ((LiteralTree) arg).getValue();
       if (systemProperties.contains(literal)) {
         AnnotatedTypeMirror type = method.getReturnType();
         type.replaceAnnotation(factory.NONNULL);
       }
     }
   }
 }
    @Override
    public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
      if (isUnderlyingTypeAValue(type)) {
        switch (tree.getKind()) {
          case BOOLEAN_LITERAL:
            AnnotationMirror boolAnno =
                createBooleanAnnotation(Collections.singletonList((Boolean) tree.getValue()));
            type.replaceAnnotation(boolAnno);
            return null;

          case CHAR_LITERAL:
            AnnotationMirror charAnno =
                createCharAnnotation(Collections.singletonList((Character) tree.getValue()));
            type.replaceAnnotation(charAnno);
            return null;

          case DOUBLE_LITERAL:
            AnnotationMirror doubleAnno =
                createNumberAnnotationMirror(
                    Collections.<Number>singletonList((Double) tree.getValue()));
            type.replaceAnnotation(doubleAnno);
            return null;

          case FLOAT_LITERAL:
            AnnotationMirror floatAnno =
                createNumberAnnotationMirror(
                    Collections.<Number>singletonList((Float) tree.getValue()));
            type.replaceAnnotation(floatAnno);
            return null;
          case INT_LITERAL:
            AnnotationMirror intAnno =
                createNumberAnnotationMirror(
                    Collections.<Number>singletonList((Integer) tree.getValue()));
            type.replaceAnnotation(intAnno);
            return null;
          case LONG_LITERAL:
            AnnotationMirror longAnno =
                createNumberAnnotationMirror(
                    Collections.<Number>singletonList((Long) tree.getValue()));
            type.replaceAnnotation(longAnno);
            return null;
          case STRING_LITERAL:
            AnnotationMirror stringAnno =
                createStringAnnotation(Collections.singletonList((String) tree.getValue()));
            type.replaceAnnotation(stringAnno);
            return null;
          default:
            return null;
        }
      }
      return null;
    }
 private AnnotatedTypeMirror postFixDouble(AnnotatedTypeMirror anno, boolean increment) {
   List<Double> values = getDoubleValues(anno.getAnnotation(DoubleVal.class));
   List<? extends Number> castedValues = NumberUtils.castNumbers(anno.getUnderlyingType(), values);
   List<Double> results = new ArrayList<>();
   for (Number value : castedValues) {
     NumberMath<?> number = NumberMath.getNumberMath(value);
     if (increment) {
       results.add(number.minus(1).doubleValue());
     } else {
       results.add(number.plus(1).doubleValue());
     }
   }
   anno.replaceAnnotation(createDoubleValAnnotation(results));
   return anno;
 }
 @Override
 public Void visitNewClass(NewClassTree node, AnnotatedTypeMirror p) {
   super.visitNewClass(node, p);
   if (useFbc) {
     boolean allCommitted = true;
     Type type = ((JCTree) node).type;
     for (ExpressionTree a : node.getArguments()) {
       final AnnotatedTypeMirror t = getAnnotatedType(a);
       allCommitted &= (isCommitted(t) || isFbcBottom(t));
     }
     if (!allCommitted) {
       p.replaceAnnotation(createFreeAnnotation(type));
     }
   }
   return null;
 }
    @Override
    public Void visitMethodInvocation(MethodInvocationTree tree, AnnotatedTypeMirror type) {
      if (isUnderlyingTypeAValue(type)
          && methodIsStaticallyExecutable(TreeUtils.elementFromUse(tree))) {
        // Get argument 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;
        }

        // Get receiver values
        AnnotatedTypeMirror receiver = getReceiverType(tree);
        List<?> receiverValues;

        if (receiver != null && !ElementUtils.isStatic(TreeUtils.elementFromUse(tree))) {
          receiverValues = getValues(receiver, receiver.getUnderlyingType());
          if (receiverValues.isEmpty()) {
            // values aren't known, so don't try to evaluate the
            // method
            return null;
          }
        } else {
          receiverValues = null;
        }

        // Evaluate method
        List<?> returnValues = evalutator.evaluteMethodCall(argValues, receiverValues, tree);
        AnnotationMirror returnType =
            resultAnnotationHandler(type.getUnderlyingType(), returnValues, tree);
        type.replaceAnnotation(returnType);
      }

      return null;
    }
    @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;
    }