package org.checkerframework.common.value;

import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.regex.qual.Regex;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.value.qual.ArrayLen;
import org.checkerframework.common.value.qual.ArrayLenRange;
import org.checkerframework.common.value.qual.BoolVal;
import org.checkerframework.common.value.qual.BottomVal;
import org.checkerframework.common.value.qual.DoubleVal;
import org.checkerframework.common.value.qual.EnumVal;
import org.checkerframework.common.value.qual.IntRange;
import org.checkerframework.common.value.qual.IntRangeFromGTENegativeOne;
import org.checkerframework.common.value.qual.IntRangeFromNonNegative;
import org.checkerframework.common.value.qual.IntRangeFromPositive;
import org.checkerframework.common.value.qual.IntVal;
import org.checkerframework.common.value.qual.MatchesRegex;
import org.checkerframework.common.value.qual.MinLen;
import org.checkerframework.common.value.qual.MinLenFieldInvariant;
import org.checkerframework.common.value.qual.PolyValue;
import org.checkerframework.common.value.qual.StringVal;
import org.checkerframework.common.value.qual.UnknownVal;
import org.checkerframework.common.value.util.Range;
import org.checkerframework.dataflow.expression.ArrayAccess;
import org.checkerframework.dataflow.expression.ArrayCreation;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.ValueLiteral;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.DefaultTypeHierarchy;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.StructuralEqualityComparer;
import org.checkerframework.framework.type.TypeHierarchy;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.LiteralTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.PropagationTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.type.typeannotator.ListTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.TypeAnnotator;
import org.checkerframework.framework.util.FieldInvariants;
import org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeKindUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;

/** AnnotatedTypeFactory for the Value type system. */
public class ValueAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
  /** Fully-qualified class name of {@link UnknownVal}. */
  public static final String UNKNOWN_NAME = "org.checkerframework.common.value.qual.UnknownVal";
  /** Fully-qualified class name of {@link BottomVal}. */
  public static final String BOTTOMVAL_NAME = "org.checkerframework.common.value.qual.BottomVal";
  /** Fully-qualified class name of {@link PolyValue}. */
  public static final String POLY_NAME = "org.checkerframework.common.value.qual.PolyValue";
  /** Fully-qualified class name of {@link ArrayLen}. */
  public static final String ARRAYLEN_NAME = "org.checkerframework.common.value.qual.ArrayLen";
  /** Fully-qualified class name of {@link BoolVal}. */
  public static final String BOOLVAL_NAME = "org.checkerframework.common.value.qual.BoolVal";
  /** Fully-qualified class name of {@link DoubleVal}. */
  public static final String DOUBLEVAL_NAME = "org.checkerframework.common.value.qual.DoubleVal";
  /** Fully-qualified class name of {@link IntVal}. */
  public static final String INTVAL_NAME = "org.checkerframework.common.value.qual.IntVal";
  /** Fully-qualified class name of {@link StringVal}. */
  public static final String STRINGVAL_NAME = "org.checkerframework.common.value.qual.StringVal";
  /** Fully-qualified class name of {@link ArrayLenRange}. */
  public static final String ARRAYLENRANGE_NAME =
      "org.checkerframework.common.value.qual.ArrayLenRange";
  /** Fully-qualified class name of {@link IntRange}. */
  public static final String INTRANGE_NAME = "org.checkerframework.common.value.qual.IntRange";

  /** Fully-qualified class name of {@link IntRangeFromGTENegativeOne}. */
  public static final String INTRANGE_FROMGTENEGONE_NAME =
      "org.checkerframework.common.value.qual.IntRangeFromGTENegativeOne";
  /** Fully-qualified class name of {@link IntRangeFromNonNegative}. */
  public static final String INTRANGE_FROMNONNEG_NAME =
      "org.checkerframework.common.value.qual.IntRangeFromNonNegative";
  /** Fully-qualified class name of {@link IntRangeFromPositive}. */
  public static final String INTRANGE_FROMPOS_NAME =
      "org.checkerframework.common.value.qual.IntRangeFromPositive";
  /** Fully-qualified class name of {@link MinLen}. */
  public static final String MINLEN_NAME = "org.checkerframework.common.value.qual.MinLen";
  /** Fully-qualified class name of {@link MatchesRegex}. */
  public static final String MATCHES_REGEX_NAME =
      "org.checkerframework.common.value.qual.MatchesRegex";

  /** The maximum number of values allowed in an annotation's array. */
  protected static final int MAX_VALUES = 10;

  /** The top type for this hierarchy. */
  protected final AnnotationMirror UNKNOWNVAL =
      AnnotationBuilder.fromClass(elements, UnknownVal.class);

  /** The bottom type for this hierarchy. */
  protected final AnnotationMirror BOTTOMVAL =
      AnnotationBuilder.fromClass(elements, BottomVal.class);

  /** The canonical @{@link PolyValue} annotation. */
  public final AnnotationMirror POLY = AnnotationBuilder.fromClass(elements, PolyValue.class);

  /** The canonical @{@link BoolVal}(true) annotation. */
  public final AnnotationMirror BOOLEAN_TRUE =
      createBooleanAnnotation(Collections.singletonList(true));

  /** The canonical @{@link BoolVal}(false) annotation. */
  public final AnnotationMirror BOOLEAN_FALSE =
      createBooleanAnnotation(Collections.singletonList(false));

  /** The value() element/field of an @ArrayLen annotation. */
  protected final ExecutableElement arrayLenValueElement =
      TreeUtils.getMethod(ArrayLen.class, "value", 0, processingEnv);
  /** The from() element/field of an @ArrayLenRange annotation. */
  protected final ExecutableElement arrayLenRangeFromElement =
      TreeUtils.getMethod(ArrayLenRange.class, "from", 0, processingEnv);
  /** The to() element/field of an @ArrayLenRange annotation. */
  protected final ExecutableElement arrayLenRangeToElement =
      TreeUtils.getMethod(ArrayLenRange.class, "to", 0, processingEnv);
  /** The value() element/field of a @BoolVal annotation. */
  protected final ExecutableElement boolValValueElement =
      TreeUtils.getMethod(BoolVal.class, "value", 0, processingEnv);
  /** The value() element/field of a @DoubleVal annotation. */
  protected final ExecutableElement doubleValValueElement =
      TreeUtils.getMethod(DoubleVal.class, "value", 0, processingEnv);
  /** The from() element/field of an @IntRange annotation. */
  protected final ExecutableElement intRangeFromElement =
      TreeUtils.getMethod(IntRange.class, "from", 0, processingEnv);
  /** The to() element/field of an @IntRange annotation. */
  protected final ExecutableElement intRangeToElement =
      TreeUtils.getMethod(IntRange.class, "to", 0, processingEnv);
  /** The value() element/field of a @IntVal annotation. */
  protected final ExecutableElement intValValueElement =
      TreeUtils.getMethod(IntVal.class, "value", 0, processingEnv);
  /** The value() element/field of a @MatchesRegex annotation. */
  public final ExecutableElement matchesRegexValueElement =
      TreeUtils.getMethod(MatchesRegex.class, "value", 0, processingEnv);
  /** The value() element/field of a @MinLen annotation. */
  protected final ExecutableElement minLenValueElement =
      TreeUtils.getMethod(MinLen.class, "value", 0, processingEnv);
  /** The field() element/field of a @MinLenFieldInvariant annotation. */
  protected final ExecutableElement minLenFieldInvariantFieldElement =
      TreeUtils.getMethod(MinLenFieldInvariant.class, "field", 0, processingEnv);
  /** The minLen() element/field of a @MinLenFieldInvariant annotation. */
  protected final ExecutableElement minLenFieldInvariantMinLenElement =
      TreeUtils.getMethod(MinLenFieldInvariant.class, "minLen", 0, processingEnv);
  /** The value() element/field of a @StringVal annotation. */
  public final ExecutableElement stringValValueElement =
      TreeUtils.getMethod(StringVal.class, "value", 0, processingEnv);

  /** Should this type factory report warnings? */
  private final boolean reportEvalWarnings;

  /** Helper class that evaluates statically executable methods, constructors, and fields. */
  // TODO: only used in ValueTreeAnnotator. Should it move there?
  protected final ReflectiveEvaluator evaluator;

  /** Helper class that holds references to special methods. */
  private final ValueMethodIdentifier methods;

  @SuppressWarnings("StaticAssignmentInConstructor") // static Range.ignoreOverflow is gross
  public ValueAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker);

    reportEvalWarnings = checker.hasOption(ValueChecker.REPORT_EVAL_WARNS);
    Range.ignoreOverflow = checker.hasOption(ValueChecker.IGNORE_RANGE_OVERFLOW);
    evaluator = new ReflectiveEvaluator(checker, this, reportEvalWarnings);

    addAliasedTypeAnnotation("android.support.annotation.IntRange", IntRange.class, true);

    // The actual ArrayLenRange is created by
    // {@link ValueAnnotatedTypeFactory#canonicalAnnotation(AnnotationMirror)};
    // this line just registers the alias. The BottomVal is never used.
    addAliasedTypeAnnotation(MinLen.class, BOTTOMVAL);

    // @Positive is aliased here because @Positive provides useful
    // information about @MinLen annotations.
    // @NonNegative and @GTENegativeOne are aliased similarly so
    // that it's possible to overwrite a function annotated to return
    // @NonNegative with, for instance, a function that returns an @IntVal(0).
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.Positive", createIntRangeFromPositive());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.NonNegative", createIntRangeFromNonNegative());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.GTENegativeOne",
        createIntRangeFromGTENegativeOne());
    // Must also alias any alias of three annotations above:
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.LengthOf", createIntRangeFromNonNegative());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.IndexFor", createIntRangeFromNonNegative());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.IndexOrHigh", createIntRangeFromNonNegative());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.IndexOrLow", createIntRangeFromGTENegativeOne());
    addAliasedTypeAnnotation(
        "org.checkerframework.checker.index.qual.SubstringIndexFor",
        createIntRangeFromGTENegativeOne());

    // PolyLength is syntactic sugar for both @PolySameLen and @PolyValue
    addAliasedTypeAnnotation("org.checkerframework.checker.index.qual.PolyLength", POLY);

    // EnumVal is treated as StringVal internally by the checker.
    addAliasedTypeAnnotation(EnumVal.class, StringVal.class, true);

    methods = new ValueMethodIdentifier(processingEnv);

    if (this.getClass() == ValueAnnotatedTypeFactory.class) {
      this.postInit();
    }
  }

  /** Gets a helper object that holds references to methods with special handling. */
  ValueMethodIdentifier getMethodIdentifier() {
    return methods;
  }

  @Override
  public AnnotationMirror canonicalAnnotation(AnnotationMirror anno) {
    if (AnnotationUtils.areSameByName(anno, MINLEN_NAME)) {
      int from = getMinLenValue(anno);
      return createArrayLenRangeAnnotation(from, Integer.MAX_VALUE);
    }

    return super.canonicalAnnotation(anno);
  }

  @Override
  protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers() {
    // Because the Value Checker includes its own alias annotations,
    // the qualifiers have to be explicitly defined.
    return new LinkedHashSet<>(
        Arrays.asList(
            ArrayLen.class,
            ArrayLenRange.class,
            IntVal.class,
            IntRange.class,
            BoolVal.class,
            StringVal.class,
            MatchesRegex.class,
            DoubleVal.class,
            BottomVal.class,
            UnknownVal.class,
            IntRangeFromPositive.class,
            IntRangeFromNonNegative.class,
            IntRangeFromGTENegativeOne.class,
            PolyValue.class));
  }

  @Override
  public CFTransfer createFlowTransferFunction(
      CFAbstractAnalysis<CFValue, CFStore, CFTransfer> analysis) {
    return new ValueTransfer(analysis);
  }

  @Override
  protected QualifierHierarchy createQualifierHierarchy() {
    return new ValueQualifierHierarchy(this, this.getSupportedTypeQualifiers());
  }

  @Override
  protected TypeHierarchy createTypeHierarchy() {
    // This is a lot of code to replace annotations so that annotations that are equivalent
    // qualifiers are the same annotation.
    return new DefaultTypeHierarchy(
        checker,
        getQualifierHierarchy(),
        checker.getBooleanOption("ignoreRawTypeArguments", true),
        checker.hasOption("invariantArrays")) {
      @Override
      public StructuralEqualityComparer createEqualityComparer() {
        return new StructuralEqualityComparer(areEqualVisitHistory) {
          @Override
          protected boolean arePrimeAnnosEqual(
              AnnotatedTypeMirror type1, AnnotatedTypeMirror type2) {
            type1.replaceAnnotation(
                convertToUnknown(
                    convertSpecialIntRangeToStandardIntRange(
                        type1.getAnnotationInHierarchy(UNKNOWNVAL))));
            type2.replaceAnnotation(
                convertToUnknown(
                    convertSpecialIntRangeToStandardIntRange(
                        type2.getAnnotationInHierarchy(UNKNOWNVAL))));

            return super.arePrimeAnnosEqual(type1, type2);
          }
        };
      }
    };
  }

  @Override
  protected TypeAnnotator createTypeAnnotator() {
    return new ListTypeAnnotator(new ValueTypeAnnotator(this), super.createTypeAnnotator());
  }

  @Override
  public FieldInvariants getFieldInvariants(TypeElement element) {
    AnnotationMirror fieldInvarAnno = getDeclAnnotation(element, MinLenFieldInvariant.class);
    if (fieldInvarAnno == null) {
      return null;
    }
    List<String> fields =
        AnnotationUtils.getElementValueArray(
            fieldInvarAnno, minLenFieldInvariantFieldElement, String.class);
    List<Integer> minlens =
        AnnotationUtils.getElementValueArray(
            fieldInvarAnno, minLenFieldInvariantMinLenElement, Integer.class);
    List<AnnotationMirror> qualifiers =
        CollectionsPlume.mapList(
            (Integer minlen) -> createArrayLenRangeAnnotation(minlen, Integer.MAX_VALUE), minlens);

    FieldInvariants superInvariants = super.getFieldInvariants(element);
    return new FieldInvariants(superInvariants, fields, qualifiers);
  }

  @Override
  protected Set<Class<? extends Annotation>> getFieldInvariantDeclarationAnnotations() {
    // include FieldInvariant so that @MinLenBottom can be used.
    Set<Class<? extends Annotation>> set =
        new HashSet<>(super.getFieldInvariantDeclarationAnnotations());
    set.add(MinLenFieldInvariant.class);
    return set;
  }

  /**
   * Creates array length annotations for the result of the Enum.values() method, which is the
   * number of possible values of the enum.
   */
  @Override
  public ParameterizedExecutableType methodFromUse(
      ExpressionTree tree, ExecutableElement methodElt, AnnotatedTypeMirror receiverType) {

    ParameterizedExecutableType superPair = super.methodFromUse(tree, methodElt, receiverType);
    if (ElementUtils.matchesElement(methodElt, "values")
        && methodElt.getEnclosingElement().getKind() == ElementKind.ENUM
        && ElementUtils.isStatic(methodElt)) {
      int count = 0;
      List<? extends Element> l = methodElt.getEnclosingElement().getEnclosedElements();
      for (Element el : l) {
        if (el.getKind() == ElementKind.ENUM_CONSTANT) {
          count++;
        }
      }
      AnnotationMirror am = createArrayLenAnnotation(Collections.singletonList(count));
      superPair.executableType.getReturnType().replaceAnnotation(am);
    }
    return superPair;
  }

  /**
   * Finds the appropriate value for the {@code from} value of an annotated type mirror containing
   * an {@code IntRange} annotation.
   *
   * @param atm an annotated type mirror that contains an {@code IntRange} annotation
   * @return either the from value from the passed int range annotation, or the minimum value of the
   *     domain of the underlying type (i.e. Integer.MIN_VALUE if the underlying type is int)
   */
  public long getFromValueFromIntRange(AnnotatedTypeMirror atm) {
    TypeMirror type = atm.getUnderlyingType();
    long defaultValue = TypeKindUtils.minValue(toPrimitiveIntegralTypeKind(type));

    AnnotationMirror intRangeAnno = atm.getAnnotation(IntRange.class);
    return getIntRangeFromValue(intRangeAnno, defaultValue);
  }

  /**
   * Finds the appropriate value for the {@code to} value of an annotated type mirror containing an
   * {@code IntRange} annotation.
   *
   * @param atm an annotated type mirror that contains an {@code IntRange} annotation
   * @return either the to value from the passed int range annotation, or the maximum value of the
   *     domain of the underlying type (i.e. Integer.MAX_VALUE if the underlying type is int)
   */
  public long getToValueFromIntRange(AnnotatedTypeMirror atm) {
    TypeMirror type = atm.getUnderlyingType();
    long defaultValue = TypeKindUtils.maxValue(toPrimitiveIntegralTypeKind(type));

    AnnotationMirror intRangeAnno = atm.getAnnotation(IntRange.class);
    return getIntRangeToValue(intRangeAnno, defaultValue);
  }

  /**
   * Gets the from() element/field out of an IntRange annotation. The from() element/field must
   * exist. Clients should call {@link #getFromValueFromIntRange} if it might not exist.
   *
   * @param intRangeAnno an IntRange annotation
   * @return its from() element/field
   */
  protected long getIntRangeFromValue(AnnotationMirror intRangeAnno) {
    return AnnotationUtils.getElementValueLong(intRangeAnno, intRangeFromElement, Long.MIN_VALUE);
  }

  /**
   * Gets the from() element/field out of an IntRange annotation. The from() element/field must
   * exist. Clients should call {@link #getFromValueFromIntRange} if it might not exist.
   *
   * @param intRangeAnno an IntRange annotation
   * @param defaultValue the value to return if there is no from() element/field
   * @return its from() element/field
   */
  protected long getIntRangeFromValue(AnnotationMirror intRangeAnno, long defaultValue) {
    return AnnotationUtils.getElementValueLong(intRangeAnno, intRangeFromElement, defaultValue);
  }

  /**
   * Gets the to() element/field out of an IntRange annotation. The to() element/field must exist.
   * Clients should call {@link #getToValueFromIntRange} if it might not exist.
   *
   * @param intRangeAnno an IntRange annotation
   * @param defaultValue the value to retur if there is no to() element/field
   * @return its to() element/field
   */
  protected long getIntRangeToValue(AnnotationMirror intRangeAnno, long defaultValue) {
    return AnnotationUtils.getElementValueLong(intRangeAnno, intRangeToElement, defaultValue);
  }

  /**
   * Gets the to() element/field out of an IntRange annotation. The to() element/field must exist.
   * Clients should call {@link #getToValueFromIntRange} if it might not exist.
   *
   * @param intRangeAnno an IntRange annotation
   * @return its to() element/field
   */
  protected long getIntRangeToValue(AnnotationMirror intRangeAnno) {
    return AnnotationUtils.getElementValueLong(intRangeAnno, intRangeToElement, Long.MAX_VALUE);
  }

  /**
   * Gets the from() element/field out of an ArrayLenRange annotation.
   *
   * @param anno an ArrayLenRange annotation
   * @return its from() element/field
   */
  protected int getArrayLenRangeFromValue(AnnotationMirror anno) {
    return AnnotationUtils.getElementValueInt(anno, arrayLenRangeFromElement, 0);
  }

  /**
   * Gets the to() element/field out of an ArrayLenRange annotation.
   *
   * @param anno an ArrayLenRange annotation
   * @return its to() element/field
   */
  protected int getArrayLenRangeToValue(AnnotationMirror anno) {
    return AnnotationUtils.getElementValueInt(anno, arrayLenRangeToElement, Integer.MAX_VALUE);
  }

  /**
   * Gets the value() element/field out of a MinLen annotation.
   *
   * @param anno a MinLen annotation
   * @return its value() element/field
   */
  protected int getMinLenValueValue(AnnotationMirror anno) {
    return AnnotationUtils.getElementValueInt(anno, minLenValueElement, 0);
  }

  /**
   * Determine the primitive integral TypeKind for the given integral type.
   *
   * @param type the type to convert, must be an integral type, boxed or primitive
   * @return one of INT, SHORT, BYTE, CHAR, or LONG
   */
  private static TypeKind toPrimitiveIntegralTypeKind(TypeMirror type) {
    TypeKind typeKind = TypeKindUtils.primitiveOrBoxedToTypeKind(type);
    if (typeKind != null && TypeKindUtils.isIntegral(typeKind)) {
      return typeKind;
    }
    throw new BugInCF(type.toString() + " expected to be an integral type.");
  }

  /**
   * Gets the values stored in either an ArrayLen annotation (ints) or an IntVal/DoubleVal/etc.
   * annotation (longs), and casts the result to a long.
   *
   * @param anno annotation mirror from which to get values
   * @return the values in {@code anno} casted to longs
   */
  /* package-private*/ List<Long> getArrayLenOrIntValue(AnnotationMirror anno) {
    if (AnnotationUtils.areSameByName(anno, ARRAYLEN_NAME)) {
      return CollectionsPlume.mapList(Integer::longValue, getArrayLength(anno));
    } else {
      return getIntValues(anno);
    }
  }

  @Override
  protected TreeAnnotator createTreeAnnotator() {
    // Don't call super.createTreeAnnotator because it includes the PropagationTreeAnnotator.
    // Only use the PropagationTreeAnnotator for typing new arrays.  The Value Checker
    // computes types differently for all other trees normally typed by the
    // PropagationTreeAnnotator.
    TreeAnnotator arrayCreation =
        new TreeAnnotator(this) {
          PropagationTreeAnnotator propagationTreeAnnotator =
              new PropagationTreeAnnotator(atypeFactory);

          @Override
          public Void visitNewArray(NewArrayTree node, AnnotatedTypeMirror mirror) {
            return propagationTreeAnnotator.visitNewArray(node, mirror);
          }
        };
    return new ListTreeAnnotator(
        new ValueTreeAnnotator(this),
        new LiteralTreeAnnotator(this).addStandardLiteralQualifiers(),
        arrayCreation);
  }

  /**
   * Converts {@link IntRangeFromPositive}, {@link IntRangeFromNonNegative}, or {@link
   * IntRangeFromGTENegativeOne} to {@link IntRange}. Any other annotation is just return.
   *
   * @param anm any annotation mirror
   * @return the int range annotation is that equivalent to {@code anm}, or {@code anm} if one
   *     doesn't exist
   */
  /* package-private */ AnnotationMirror convertSpecialIntRangeToStandardIntRange(
      AnnotationMirror anm) {
    if (AnnotationUtils.areSameByName(anm, INTRANGE_FROMPOS_NAME)) {
      return createIntRangeAnnotation(1, Integer.MAX_VALUE);
    }

    if (AnnotationUtils.areSameByName(anm, INTRANGE_FROMNONNEG_NAME)) {
      return createIntRangeAnnotation(0, Integer.MAX_VALUE);
    }

    if (AnnotationUtils.areSameByName(anm, INTRANGE_FROMGTENEGONE_NAME)) {
      return createIntRangeAnnotation(-1, Integer.MAX_VALUE);
    }
    return anm;
  }

  /**
   * If {@code anno} is equivalent to UnknownVal, return UnknownVal; otherwise, return {@code anno}.
   *
   * @param anno any annotation mirror
   * @return UnknownVal if {@code anno} is equivalent to it; otherwise, return {@code anno}
   */
  /* package-private */ AnnotationMirror convertToUnknown(AnnotationMirror anno) {
    if (AnnotationUtils.areSameByName(anno, ARRAYLENRANGE_NAME)) {
      Range range = getRange(anno);
      if (range.from == 0 && range.to >= Integer.MAX_VALUE) {
        return UNKNOWNVAL;
      }
    } else if (AnnotationUtils.areSameByName(anno, INTRANGE_NAME)) {
      Range range = getRange(anno);
      if (range.isLongEverything()) {
        return UNKNOWNVAL;
      }
    }
    return anno;
  }

  /**
   * Returns the estimate for the length of a string or array with whose annotated type is {@code
   * type}.
   *
   * @param type annotated typed
   * @return the estimate for the length of a string or array with whose annotated type is {@code
   *     type}.
   */
  /* package-private */ AnnotationMirror createArrayLengthResultAnnotation(
      AnnotatedTypeMirror type) {
    AnnotationMirror arrayAnno = type.getAnnotationInHierarchy(UNKNOWNVAL);
    switch (AnnotationUtils.annotationName(arrayAnno)) {
      case ARRAYLEN_NAME:
        // array.length, where array : @ArrayLen(x)
        List<Integer> lengths = getArrayLength(arrayAnno);
        return createNumberAnnotationMirror(new ArrayList<>(lengths));
      case ARRAYLENRANGE_NAME:
        // array.length, where array : @ArrayLenRange(x)
        Range range = getRange(arrayAnno);
        return createIntRangeAnnotation(range);
      case STRINGVAL_NAME:
        List<String> strings = getStringValues(arrayAnno);
        List<Integer> lengthsS = ValueCheckerUtils.getLengthsForStringValues(strings);
        return createNumberAnnotationMirror(new ArrayList<>(lengthsS));
      default:
        return createIntRangeAnnotation(0, Integer.MAX_VALUE);
    }
  }

  /**
   * Returns a constant value annotation with the {@code value}. The class of the annotation
   * reflects the {@code resultType} given.
   *
   * @param resultType used to select which kind of value annotation is returned
   * @param value value to use
   * @return a constant value annotation with the {@code value}
   */
  /* package-private */ AnnotationMirror createResultingAnnotation(
      TypeMirror resultType, Object value) {
    return createResultingAnnotation(resultType, Collections.singletonList(value));
  }

  /**
   * Returns a constant value annotation with the {@code values}. The class of the annotation
   * reflects the {@code resultType} given.
   *
   * @param resultType used to select which kind of value annotation is returned
   * @param values must be a homogeneous list: every element of it has the same class
   * @return a constant value annotation with the {@code values}
   */
  /* package-private */ AnnotationMirror createResultingAnnotation(
      TypeMirror resultType, List<?> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    // For some reason null is included in the list of values,
    // so remove it so that it does not cause a NPE elsewhere.
    values.remove(null);
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }

    if (TypesUtils.isString(resultType)) {
      List<String> stringVals = CollectionsPlume.mapList((Object o) -> (String) o, values);
      return createStringAnnotation(stringVals);
    } else if (TypesUtils.getClassFromType(resultType) == char[].class) {
      List<String> stringVals =
          CollectionsPlume.mapList(
              (Object o) -> {
                if (o instanceof char[]) {
                  return new String((char[]) o);
                } else {
                  return o.toString();
                }
              },
              values);
      return createStringAnnotation(stringVals);
    }

    TypeKind primitiveKind;
    if (TypesUtils.isPrimitive(resultType)) {
      primitiveKind = resultType.getKind();
    } else if (TypesUtils.isBoxedPrimitive(resultType)) {
      primitiveKind = types.unboxedType(resultType).getKind();
    } else {
      return UNKNOWNVAL;
    }

    switch (primitiveKind) {
      case BOOLEAN:
        List<Boolean> boolVals = CollectionsPlume.mapList((Object o) -> (Boolean) o, values);
        return createBooleanAnnotation(boolVals);
      case DOUBLE:
      case FLOAT:
      case INT:
      case LONG:
      case SHORT:
      case BYTE:
        List<Number> numberVals = new ArrayList<>(values.size());
        List<Character> characterVals = new ArrayList<>(values.size());
        for (Object o : values) {
          if (o instanceof Character) {
            characterVals.add((Character) o);
          } else {
            numberVals.add((Number) o);
          }
        }
        if (numberVals.isEmpty()) {
          return createCharAnnotation(characterVals);
        }
        return createNumberAnnotationMirror(new ArrayList<>(numberVals));
      case CHAR:
        List<Character> charVals = new ArrayList<>(values.size());
        for (Object o : values) {
          if (o instanceof Number) {
            charVals.add((char) ((Number) o).intValue());
          } else {
            charVals.add((char) o);
          }
        }
        return createCharAnnotation(charVals);
      default:
        throw new UnsupportedOperationException("Unexpected kind:" + resultType);
    }
  }

  /**
   * Returns a {@link IntVal} or {@link IntRange} annotation using the values. If {@code values} is
   * null, then UnknownVal is returned; if {@code values} is empty, then bottom is returned. If the
   * number of {@code values} is greater than MAX_VALUES, return an {@link IntRange}. In other
   * cases, the values are sorted and duplicates are removed before an {@link IntVal} is created.
   *
   * @param values list of longs; duplicates are allowed and the values may be in any order
   * @return an annotation depends on the values
   */
  public AnnotationMirror createIntValAnnotation(List<Long> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      long valMin = Collections.min(values);
      long valMax = Collections.max(values);
      return createIntRangeAnnotation(valMin, valMax);
    } else {
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, IntVal.class);
      builder.setValue("value", values);
      return builder.build();
    }
  }

  /**
   * Convert an {@code @IntRange} annotation to an {@code @IntVal} annotation, or to UNKNOWNVAL if
   * the input is too wide to be represented as an {@code @IntVal}.
   *
   * @param intRangeAnno an {@code @IntRange} annotation
   * @return an {@code @IntVal} annotation corresponding to the argument
   */
  public AnnotationMirror convertIntRangeToIntVal(AnnotationMirror intRangeAnno) {
    Range range = getRange(intRangeAnno);
    List<Long> values = ValueCheckerUtils.getValuesFromRange(range, Long.class);
    return createIntValAnnotation(values);
  }

  /**
   * Returns a {@link DoubleVal} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created.
   *
   * @param values list of doubles; duplicates are allowed and the values may be in any order
   * @return a {@link DoubleVal} annotation using the values
   */
  public AnnotationMirror createDoubleValAnnotation(List<Double> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      return UNKNOWNVAL;
    } else {
      Collections.sort(values);
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, DoubleVal.class);
      builder.setValue("value", values);
      return builder.build();
    }
  }

  /** Convert an {@code @IntVal} annotation to a {@code @DoubleVal} annotation. */
  /* package-private */ AnnotationMirror convertIntValToDoubleVal(AnnotationMirror intValAnno) {
    List<Long> intValues = getIntValues(intValAnno);
    return createDoubleValAnnotation(convertLongListToDoubleList(intValues));
  }

  /**
   * Convert a {@code List<Long>} to a {@code List<Double>}.
   *
   * @param intValues a list of long integers
   * @return a list of double floating-point values
   */
  /* package-private */ List<Double> convertLongListToDoubleList(List<Long> intValues) {
    return CollectionsPlume.mapList(Long::doubleValue, intValues);
  }

  /**
   * Returns a {@link StringVal} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created. If values is larger than
   * the max number of values allowed (10 by default), then an {@link ArrayLen} or an {@link
   * ArrayLenRange} annotation is returned.
   *
   * @param values list of strings; duplicates are allowed and the values may be in any order
   * @return a {@link StringVal} annotation using the values
   */
  public AnnotationMirror createStringAnnotation(List<String> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      // Too many strings are replaced by their lengths
      List<Integer> lengths = ValueCheckerUtils.getLengthsForStringValues(values);
      return createArrayLenAnnotation(lengths);
    } else {
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, StringVal.class);
      builder.setValue("value", values);
      return builder.build();
    }
  }

  /**
   * Returns a {@link ArrayLen} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created. If values is larger than
   * the max number of values allowed (10 by default), then an {@link ArrayLenRange} annotation is
   * returned.
   *
   * @param values list of integers; duplicates are allowed and the values may be in any order
   * @return a {@link ArrayLen} annotation using the values
   */
  public AnnotationMirror createArrayLenAnnotation(List<Integer> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.isEmpty() || Collections.min(values) < 0) {
      return BOTTOMVAL;
    } else if (values.size() > MAX_VALUES) {
      return createArrayLenRangeAnnotation(Collections.min(values), Collections.max(values));
    } else {
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, ArrayLen.class);
      builder.setValue("value", values);
      return builder.build();
    }
  }

  /**
   * Returns a {@link BoolVal} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created.
   *
   * @param values list of booleans; duplicates are allowed and the values may be in any order
   * @return a {@link BoolVal} annotation using the values
   */
  public AnnotationMirror createBooleanAnnotation(List<Boolean> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      return UNKNOWNVAL;
    } else {
      // TODO: This seems wasteful.  Why not create the 3 interesting AnnotationMirrors (with
      // arguments {true}, {false}, and {true, false}, respectively) in advance and return one
      // of them?  (Maybe an advantage of this implementation is that it is identical to
      // some other implementations and therefore might be less error-prone.)
      AnnotationBuilder builder = new AnnotationBuilder(processingEnv, BoolVal.class);
      builder.setValue("value", values);
      return builder.build();
    }
  }

  /**
   * Returns a {@link IntVal} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created.
   *
   * @param values list of characters; duplicates are allowed and the values may be in any order
   * @return a {@link IntVal} annotation using the values
   */
  public AnnotationMirror createCharAnnotation(List<Character> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      return UNKNOWNVAL;
    } else {
      List<Long> longValues = CollectionsPlume.mapList((Character value) -> (long) value, values);
      return createIntValAnnotation(longValues);
    }
  }

  /**
   * Returns a {@link DoubleVal} annotation using the values. If {@code values} is null, then
   * UnknownVal is returned; if {@code values} is empty, then bottom is returned. The values are
   * sorted and duplicates are removed before the annotation is created.
   *
   * @param values list of doubleacters; duplicates are allowed and the values may be in any order
   * @return a {@link IntVal} annotation using the values
   */
  public AnnotationMirror createDoubleAnnotation(List<Double> values) {
    if (values == null) {
      return UNKNOWNVAL;
    }
    if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    values = CollectionsPlume.withoutDuplicates(values);
    if (values.size() > MAX_VALUES) {
      return UNKNOWNVAL;
    } else {
      return createDoubleValAnnotation(values);
    }
  }

  /**
   * Returns an annotation that represents the given set of values.
   *
   * @param values a homogeneous list: every element of it has the same class
   * @return an annotation that represents the given set of values
   */
  public AnnotationMirror createNumberAnnotationMirror(List<Number> values) {
    if (values == null) {
      return UNKNOWNVAL;
    } else if (values.isEmpty()) {
      return BOTTOMVAL;
    }
    Number first = values.get(0);
    if (first instanceof Integer
        || first instanceof Short
        || first instanceof Long
        || first instanceof Byte) {
      List<Long> intValues = CollectionsPlume.mapList(Number::longValue, values);
      return createIntValAnnotation(intValues);
    } else if (first instanceof Double || first instanceof Float) {
      List<Double> intValues = CollectionsPlume.mapList(Number::doubleValue, values);
      return createDoubleValAnnotation(intValues);
    }
    throw new UnsupportedOperationException(
        "ValueAnnotatedTypeFactory: unexpected class: " + first.getClass());
  }

  /**
   * Create an {@code @IntRange} annotation from the two (inclusive) bounds. Does not return
   * BOTTOMVAL or UNKNOWNVAL.
   */
  /* package-private */ AnnotationMirror createIntRangeAnnotation(long from, long to) {
    assert from <= to;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, IntRange.class);
    builder.setValue("from", from);
    builder.setValue("to", to);
    return builder.build();
  }

  /**
   * Create an {@code @IntRange} or {@code @IntVal} annotation from the range. May return BOTTOMVAL
   * or UNKNOWNVAL.
   */
  public AnnotationMirror createIntRangeAnnotation(Range range) {
    if (range.isNothing()) {
      return BOTTOMVAL;
    } else if (range.isLongEverything()) {
      return UNKNOWNVAL;
    } else if (range.isWiderThan(MAX_VALUES)) {
      return createIntRangeAnnotation(range.from, range.to);
    } else {
      List<Long> newValues = ValueCheckerUtils.getValuesFromRange(range, Long.class);
      return createIntValAnnotation(newValues);
    }
  }

  /**
   * Creates the special {@link IntRangeFromPositive} annotation, which is only used as an alias for
   * the Index Checker's {@link org.checkerframework.checker.index.qual.Positive} annotation. It is
   * treated everywhere as an IntRange annotation, but is not checked when it appears as the left
   * hand side of an assignment (because the Lower Bound Checker will check it).
   */
  private AnnotationMirror createIntRangeFromPositive() {
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, IntRangeFromPositive.class);
    return builder.build();
  }

  /**
   * Creates the special {@link IntRangeFromNonNegative} annotation, which is only used as an alias
   * for the Index Checker's {@link org.checkerframework.checker.index.qual.NonNegative} annotation.
   * It is treated everywhere as an IntRange annotation, but is not checked when it appears as the
   * left hand side of an assignment (because the Lower Bound Checker will check it).
   */
  private AnnotationMirror createIntRangeFromNonNegative() {
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, IntRangeFromNonNegative.class);
    return builder.build();
  }

  /**
   * Creates the special {@link IntRangeFromGTENegativeOne} annotation, which is only used as an
   * alias for the Index Checker's {@link org.checkerframework.checker.index.qual.GTENegativeOne}
   * annotation. It is treated everywhere as an IntRange annotation, but is not checked when it
   * appears as the left hand side of an assignment (because the Lower Bound Checker will check it).
   */
  private AnnotationMirror createIntRangeFromGTENegativeOne() {
    AnnotationBuilder builder =
        new AnnotationBuilder(processingEnv, IntRangeFromGTENegativeOne.class);
    return builder.build();
  }

  /**
   * Create an {@code @ArrayLenRange} annotation from the two (inclusive) bounds. Does not return
   * BOTTOMVAL or UNKNOWNVAL.
   */
  public AnnotationMirror createArrayLenRangeAnnotation(int from, int to) {
    assert from <= to;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, ArrayLenRange.class);
    builder.setValue("from", from);
    builder.setValue("to", to);
    return builder.build();
  }

  /**
   * Create an {@code @ArrayLenRange} annotation from the range. May return BOTTOMVAL or UNKNOWNVAL.
   */
  public AnnotationMirror createArrayLenRangeAnnotation(Range range) {
    if (range.isNothing()) {
      return BOTTOMVAL;
    } else if (range.isLongEverything() || !range.isWithinInteger()) {
      return UNKNOWNVAL;
    } else {
      return createArrayLenRangeAnnotation(
          Long.valueOf(range.from).intValue(), Long.valueOf(range.to).intValue());
    }
  }

  /**
   * Creates an {@code MatchesRegex} annotation for the given regular expressions.
   *
   * @param regexes a list of Java regular expressions
   * @return a MatchesRegex annotation with those values
   */
  public AnnotationMirror createMatchesRegexAnnotation(@Nullable List<@Regex String> regexes) {
    if (regexes == null) {
      return UNKNOWNVAL;
    }
    if (regexes.isEmpty()) {
      return BOTTOMVAL;
    }
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, MatchesRegex.class);
    builder.setValue("value", regexes.toArray(new String[0]));
    return builder.build();
  }

  /**
   * Converts an {@code @StringVal} annotation to an {@code @ArrayLenRange} annotation.
   *
   * @param stringValAnno a StringVal annotation
   * @return an ArrayLenRange annotation representing the possible lengths of the values of the
   *     given StringVal annotation
   */
  /* package-private */ AnnotationMirror convertStringValToArrayLenRange(
      AnnotationMirror stringValAnno) {
    List<String> values = getStringValues(stringValAnno);
    List<Integer> lengths = ValueCheckerUtils.getLengthsForStringValues(values);
    return createArrayLenRangeAnnotation(Collections.min(lengths), Collections.max(lengths));
  }

  /**
   * Converts an {@code @StringVal} annotation to an {@code @ArrayLen} annotation. If the
   * {@code @StringVal} annotation contains string values of more than MAX_VALUES distinct lengths,
   * {@code @ArrayLenRange} annotation is returned instead.
   */
  /* package-private */ AnnotationMirror convertStringValToArrayLen(
      AnnotationMirror stringValAnno) {
    List<String> values = getStringValues(stringValAnno);
    return createArrayLenAnnotation(ValueCheckerUtils.getLengthsForStringValues(values));
  }

  /**
   * Converts an {@code StringVal} annotation to an {@code MatchesRegex} annotation that matches
   * exactly the string values listed in the {@code StringVal}.
   *
   * @param stringValAnno a StringVal annotation
   * @return an equivalent MatchesReges annotation
   */
  /* package-private */ AnnotationMirror convertStringValToMatchesRegex(
      AnnotationMirror stringValAnno) {
    List<String> values = getStringValues(stringValAnno);
    List<@Regex String> valuesAsRegexes = CollectionsPlume.mapList(Pattern::quote, values);
    return createMatchesRegexAnnotation(valuesAsRegexes);
  }

  /**
   * Converts an {@code @ArrayLen} annotation to an {@code @ArrayLenRange} annotation.
   *
   * @param arrayLenAnno an ArrayLen annotation
   * @return an ArrayLenRange annotation representing the bounds of the given ArrayLen annotation
   */
  public AnnotationMirror convertArrayLenToArrayLenRange(AnnotationMirror arrayLenAnno) {
    List<Integer> values = getArrayLength(arrayLenAnno);
    return createArrayLenRangeAnnotation(Collections.min(values), Collections.max(values));
  }

  /** Converts an {@code @IntVal} annotation to an {@code @IntRange} annotation. */
  public AnnotationMirror convertIntValToIntRange(AnnotationMirror intValAnno) {
    List<Long> intValues = getIntValues(intValAnno);
    return createIntRangeAnnotation(Collections.min(intValues), Collections.max(intValues));
  }

  /**
   * Returns a {@link Range} bounded by the values specified in the given {@code @Range} annotation.
   * Also returns an appropriate range if an {@code @IntVal} annotation is passed. Returns {@code
   * null} if the annotation is null or if the annotation is not an {@code IntRange}, {@code
   * IntRangeFromPositive}, {@code IntVal}, or {@code ArrayLenRange}.
   *
   * @param rangeAnno a {@code @Range} annotation
   * @return the {@link Range} that the annotation represents
   */
  public Range getRange(AnnotationMirror rangeAnno) {
    if (rangeAnno == null) {
      return null;
    }
    switch (AnnotationUtils.annotationName(rangeAnno)) {
      case INTRANGE_FROMPOS_NAME:
        return Range.create(1, Integer.MAX_VALUE);
      case INTRANGE_FROMNONNEG_NAME:
        return Range.create(0, Integer.MAX_VALUE);
      case INTRANGE_FROMGTENEGONE_NAME:
        return Range.create(-1, Integer.MAX_VALUE);
      case INTVAL_NAME:
        return ValueCheckerUtils.getRangeFromValues(getIntValues(rangeAnno));
      case INTRANGE_NAME:
        // Assume rangeAnno is well-formed, i.e., 'from' is less than or equal to 'to'.
        return Range.create(getIntRangeFromValue(rangeAnno), getIntRangeToValue(rangeAnno));
      case ARRAYLENRANGE_NAME:
        return Range.create(
            getArrayLenRangeFromValue(rangeAnno), getArrayLenRangeToValue(rangeAnno));
      default:
        return null;
    }
  }

  /**
   * Returns the set of possible values as a sorted list with no duplicate values. Returns the empty
   * list if no values are possible (for dead code). Returns null if any value is possible -- that
   * is, if no estimate can be made -- and this includes when there is no constant-value annotation
   * so the argument is null.
   *
   * <p>The method returns a list of {@code Long} but is named {@code getIntValues} because it
   * supports the {@code @IntVal} annotation.
   *
   * @param intAnno an {@code @IntVal} annotation, or null
   * @return the possible values, deduplicated and sorted
   */
  public List<Long> getIntValues(AnnotationMirror intAnno) {
    if (intAnno == null) {
      return null;
    }
    List<Long> list = AnnotationUtils.getElementValueArray(intAnno, intValValueElement, Long.class);
    list = CollectionsPlume.withoutDuplicates(list);
    return list;
  }

  /**
   * Returns the set of possible values as a sorted list with no duplicate values. Returns the empty
   * list if no values are possible (for dead code). Returns null if any value is possible -- that
   * is, if no estimate can be made -- and this includes when there is no constant-value annotation
   * so the argument is null.
   *
   * @param doubleAnno a {@code @DoubleVal} annotation, or null
   * @return the possible values, deduplicated and sorted
   */
  public List<Double> getDoubleValues(AnnotationMirror doubleAnno) {
    if (doubleAnno == null) {
      return null;
    }
    List<Double> list =
        AnnotationUtils.getElementValueArray(doubleAnno, doubleValValueElement, Double.class);
    list = CollectionsPlume.withoutDuplicates(list);
    return list;
  }

  /**
   * Returns the set of possible array lengths as a sorted list with no duplicate values. Returns
   * the empty list if no values are possible (for dead code). Returns null if any value is possible
   * -- that is, if no estimate can be made -- and this includes when there is no constant-value
   * annotation so the argument is null.
   *
   * @param arrayAnno an {@code @ArrayLen} annotation, or null
   * @return the possible array lengths, deduplicated and sorted
   */
  public List<Integer> getArrayLength(AnnotationMirror arrayAnno) {
    if (arrayAnno == null) {
      return null;
    }
    List<Integer> list =
        AnnotationUtils.getElementValueArray(arrayAnno, arrayLenValueElement, Integer.class);
    list = CollectionsPlume.withoutDuplicates(list);
    return list;
  }

  /**
   * Returns the set of possible values as a sorted list with no duplicate values. Returns the empty
   * list if no values are possible (for dead code). Returns null if any value is possible -- that
   * is, if no estimate can be made -- and this includes when there is no constant-value annotation
   * so the argument is null.
   *
   * @param intAnno an {@code @IntVal} annotation, or null
   * @return the values represented by the given {@code @IntVal} annotation
   */
  public List<Character> getCharValues(AnnotationMirror intAnno) {
    if (intAnno == null) {
      return Collections.emptyList();
    }
    List<Long> intValues =
        AnnotationUtils.getElementValueArray(intAnno, intValValueElement, Long.class);
    List<Character> charValues =
        CollectionsPlume.mapList((Long i) -> (char) i.intValue(), intValues);
    Collections.sort(charValues);
    // TODO: Should this be an unmodifiable list?
    return new ArrayList<>(charValues);
  }

  /**
   * Returns the single possible boolean value, or null if there is not exactly one possible value.
   *
   * @see #getBooleanValues
   * @param boolAnno a {@code @BoolVal} annotation, or null
   * @return the single possible boolean value, on null if that is not the case
   */
  public Boolean getBooleanValue(AnnotationMirror boolAnno) {
    if (boolAnno == null) {
      return null;
    }
    List<Boolean> boolValues =
        AnnotationUtils.getElementValueArray(boolAnno, boolValValueElement, Boolean.class);
    Set<Boolean> boolSet = new TreeSet<>(boolValues);
    if (boolSet.size() == 1) {
      return boolSet.iterator().next();
    }
    return null;
  }

  /**
   * Returns the set of possible boolean values as a sorted list with no duplicate values. Returns
   * the empty list if no values are possible (for dead code). Returns null if any value is possible
   * -- that is, if no estimate can be made -- and this includes when there is no constant-value
   * annotation so the argument is null.
   *
   * @param boolAnno a {@code @BoolVal} annotation, or null
   * @return a singleton or empty list of possible boolean values, or null
   */
  public @Nullable List<Boolean> getBooleanValues(AnnotationMirror boolAnno) {
    if (boolAnno == null) {
      return Collections.emptyList();
    }
    List<Boolean> boolValues =
        AnnotationUtils.getElementValueArray(boolAnno, boolValValueElement, Boolean.class);
    if (boolValues.size() < 2) {
      return boolValues;
    }
    // Remove duplicates.
    Set<Boolean> boolSet = new TreeSet<>(boolValues);
    if (boolSet.size() > 1) {
      // boolSet={true,false};
      return null;
    }
    return new ArrayList<>(boolSet);
  }

  /**
   * Returns the set of possible values as a sorted list with no duplicate values. Returns the empty
   * list if no values are possible (for dead code). Returns null if any value is possible -- that
   * is, if no estimate can be made -- and this includes when there is no constant-value annotation
   * so the argument is null.
   *
   * @param stringAnno a {@code @StringVal} annotation, or null
   * @return the possible values, deduplicated and sorted
   */
  public List<String> getStringValues(AnnotationMirror stringAnno) {
    if (stringAnno == null) {
      return null;
    }
    List<String> list =
        AnnotationUtils.getElementValueArray(stringAnno, stringValValueElement, String.class);
    list = CollectionsPlume.withoutDuplicates(list);
    return list;
  }

  /**
   * Returns the set of possible values as a sorted list with no duplicate values. Returns the empty
   * list if no values are possible (for dead code). Returns null if any value is possible -- that
   * is, if no estimate can be made -- and this includes when there is no constant-value annotation
   * so the argument is null.
   *
   * @param matchesRegexAnno a {@code @MatchesRegex} annotation, or null
   * @return the possible values, deduplicated and sorted
   */
  public List<String> getMatchesRegexValues(AnnotationMirror matchesRegexAnno) {
    if (matchesRegexAnno == null) {
      return null;
    }
    List<String> list =
        AnnotationUtils.getElementValueArray(
            matchesRegexAnno, matchesRegexValueElement, String.class);
    list = CollectionsPlume.withoutDuplicates(list);
    return list;
  }

  public boolean isIntRange(Set<AnnotationMirror> anmSet) {
    for (AnnotationMirror anm : anmSet) {
      if (isIntRange(anm)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if {@code anno} is an {@link IntRange}, {@link IntRangeFromPositive}, {@link
   * IntRangeFromNonNegative}, or {@link IntRangeFromGTENegativeOne}.
   *
   * @param anno annotation mirror
   * @return true if {@code anno} is an {@link IntRange}, {@link IntRangeFromPositive}, {@link
   *     IntRangeFromNonNegative}, or {@link IntRangeFromGTENegativeOne}
   */
  public boolean isIntRange(AnnotationMirror anno) {
    String name = AnnotationUtils.annotationName(anno);
    return name.equals(INTRANGE_NAME)
        || name.equals(INTRANGE_FROMPOS_NAME)
        || name.equals(INTRANGE_FROMNONNEG_NAME)
        || name.equals(INTRANGE_FROMGTENEGONE_NAME);
  }

  public int getMinLenValue(AnnotatedTypeMirror atm) {
    return getMinLenValue(atm.getAnnotationInHierarchy(UNKNOWNVAL));
  }

  /**
   * Used to find the maximum length of an array. Returns null if there is no minimum length known,
   * or if the passed annotation is null.
   */
  public Integer getMaxLenValue(AnnotationMirror annotation) {
    if (annotation == null) {
      return null;
    }
    switch (AnnotationUtils.annotationName(annotation)) {
      case ARRAYLENRANGE_NAME:
        return Long.valueOf(getRange(annotation).to).intValue();
      case ARRAYLEN_NAME:
        return Collections.max(getArrayLength(annotation));
      case STRINGVAL_NAME:
        return Collections.max(
            ValueCheckerUtils.getLengthsForStringValues(getStringValues(annotation)));
      default:
        return null;
    }
  }

  /**
   * Finds a minimum length of an array specified by the provided annotation. Returns null if there
   * is no minimum length known, or if the passed annotation is null.
   *
   * <p>Note that this routine handles actual {@link MinLen} annotations, because it is called by
   * {@link ValueAnnotatedTypeFactory#canonicalAnnotation(AnnotationMirror)}, which transforms
   * {@link MinLen} annotations into {@link ArrayLenRange} annotations.
   */
  private Integer getSpecifiedMinLenValue(AnnotationMirror annotation) {
    if (annotation == null) {
      return null;
    }
    switch (AnnotationUtils.annotationName(annotation)) {
      case MINLEN_NAME:
        return getMinLenValueValue(annotation);
      case ARRAYLENRANGE_NAME:
        return Long.valueOf(getRange(annotation).from).intValue();
      case ARRAYLEN_NAME:
        return Collections.min(getArrayLength(annotation));
      case STRINGVAL_NAME:
        return Collections.min(
            ValueCheckerUtils.getLengthsForStringValues(getStringValues(annotation)));
      default:
        return null;
    }
  }

  /**
   * Used to find the minimum length of an array, which is useful for array bounds checking. Returns
   * 0 if there is no minimum length known, or if the passed annotation is null.
   *
   * <p>Note that this routine handles actual {@link MinLen} annotations, because it is called by
   * {@link ValueAnnotatedTypeFactory#canonicalAnnotation(AnnotationMirror)}, which transforms
   * {@link MinLen} annotations into {@link ArrayLenRange} annotations.
   */
  public int getMinLenValue(AnnotationMirror annotation) {
    Integer minLen = getSpecifiedMinLenValue(annotation);
    if (minLen == null || minLen < 0) {
      return 0;
    } else {
      return minLen;
    }
  }

  /**
   * Returns the minimum length of an array.
   *
   * @param annotations the annotations on the array expression
   * @return the minimum length of an array
   */
  public int getMinLenValue(Set<AnnotationMirror> annotations) {
    int result = 0;
    for (AnnotationMirror annotation : annotations) {
      Integer minLen = getSpecifiedMinLenValue(annotation);
      if (minLen != null) {
        result = Integer.min(result, minLen);
      }
    }
    if (result < 0) {
      return 0;
    } else {
      return result;
    }
  }

  /**
   * Returns the smallest possible value that an integral annotation might take on. The passed
   * {@code AnnotatedTypeMirror} should contain either an {@code @IntRange} annotation or an
   * {@code @IntVal} annotation. Returns null if it does not.
   *
   * @param atm annotated type
   * @return the smallest possible integral for which the {@code atm} could be the type
   */
  public Long getMinimumIntegralValue(AnnotatedTypeMirror atm) {
    AnnotationMirror anm = atm.getAnnotationInHierarchy(UNKNOWNVAL);
    if (AnnotationUtils.areSameByName(anm, INTVAL_NAME)) {
      List<Long> possibleValues = getIntValues(anm);
      return Collections.min(possibleValues);
    } else if (isIntRange(anm)) {
      Range range = getRange(anm);
      return range.from;
    }
    return null;
  }

  /**
   * Returns the minimum length of an array expression or 0 if the min length is unknown.
   *
   * @param sequenceExpression Java expression
   * @param tree expression tree or variable declaration
   * @param currentPath path to local scope
   * @return min length of sequenceExpression or 0
   */
  public int getMinLenFromString(String sequenceExpression, Tree tree, TreePath currentPath) {
    AnnotationMirror lengthAnno;
    JavaExpression expressionObj;
    try {
      expressionObj = parseJavaExpressionString(sequenceExpression, currentPath);
    } catch (JavaExpressionParseException e) {
      // ignore parse errors and return 0.
      return 0;
    }

    if (expressionObj instanceof ValueLiteral) {
      ValueLiteral sequenceLiteral = (ValueLiteral) expressionObj;
      Object sequenceLiteralValue = sequenceLiteral.getValue();
      if (sequenceLiteralValue instanceof String) {
        return ((String) sequenceLiteralValue).length();
      }
    } else if (expressionObj instanceof ArrayCreation) {
      ArrayCreation arrayCreation = (ArrayCreation) expressionObj;
      // This is only expected to support array creations in varargs methods
      return arrayCreation.getInitializers().size();
    } else if (expressionObj instanceof ArrayAccess) {
      List<? extends AnnotationMirror> annoList = expressionObj.getType().getAnnotationMirrors();
      for (AnnotationMirror anno : annoList) {
        String ANNO_NAME = AnnotationUtils.annotationName(anno);
        if (ANNO_NAME.equals(MINLEN_NAME)) {
          return getMinLenValue(canonicalAnnotation(anno));
        } else if (ANNO_NAME.equals(ARRAYLEN_NAME) || ANNO_NAME.equals(ARRAYLENRANGE_NAME)) {
          return getMinLenValue(anno);
        }
      }
    }

    lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, ArrayLenRange.class);
    if (lengthAnno == null) {
      lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, ArrayLen.class);
    }
    if (lengthAnno == null) {
      lengthAnno = getAnnotationFromJavaExpression(expressionObj, tree, StringVal.class);
    }

    if (lengthAnno == null) {
      // Could not find a more precise type, so return 0;
      return 0;
    }

    return getMinLenValue(lengthAnno);
  }

  /**
   * Returns the annotation type mirror for the type of {@code expressionTree} with default
   * annotations applied.
   */
  @Override
  public AnnotatedTypeMirror getDummyAssignedTo(ExpressionTree expressionTree) {
    TypeMirror type = TreeUtils.typeOf(expressionTree);
    if (type.getKind() != TypeKind.VOID) {
      AnnotatedTypeMirror atm = type(expressionTree);
      addDefaultAnnotations(atm);
      return atm;
    }
    return null;
  }
}
