package org.checkerframework.framework.type;

import com.sun.tools.javac.code.Symbol.MethodSymbol;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
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.element.TypeParameterElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.Types;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.checkerframework.framework.type.visitor.AnnotatedTypeVisitor;
import org.checkerframework.framework.util.element.ElementAnnotationUtil.ErrorTypeKindException;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TypeKindUtils;
import org.plumelib.util.CollectionsPlume;

/**
 * Represents an annotated type in the Java programming language. Types include primitive types,
 * declared types (class and interface types), array types, type variables, and the null type. Also
 * represented are wildcard type arguments, the signature and return types of executables, and
 * pseudo-types corresponding to packages and to the keyword {@code void}.
 *
 * <p>To implement operations based on the class of an {@code AnnotatedTypeMirror} object, either
 * use a visitor or use the result of the {@link #getKind()} method.
 *
 * @see TypeMirror
 */
public abstract class AnnotatedTypeMirror {

  /**
   * Creates an AnnotatedTypeMirror for the provided type. The result contains no annotations.
   *
   * @param type the underlying type for the resulting AnnotatedTypeMirror
   * @param atypeFactory the type factory that will build the result
   * @param isDeclaration true if the result should represent a declaration, rather than a use, of a
   *     type
   * @return an AnnotatedTypeMirror whose underlying type is {@code type}
   */
  public static AnnotatedTypeMirror createType(
      TypeMirror type, AnnotatedTypeFactory atypeFactory, boolean isDeclaration) {
    if (type == null) {
      throw new BugInCF("AnnotatedTypeMirror.createType: input type must not be null");
    }

    AnnotatedTypeMirror result;
    switch (type.getKind()) {
      case ARRAY:
        result = new AnnotatedArrayType((ArrayType) type, atypeFactory);
        break;
      case DECLARED:
        result = new AnnotatedDeclaredType((DeclaredType) type, atypeFactory, isDeclaration);
        break;
      case ERROR:
        throw new BugInCF(
            "AnnotatedTypeMirror.createType: input is not compilable. Found error type: " + type);

      case EXECUTABLE:
        result = new AnnotatedExecutableType((ExecutableType) type, atypeFactory);
        break;
      case VOID:
      case PACKAGE:
      case NONE:
        result = new AnnotatedNoType((NoType) type, atypeFactory);
        break;
      case NULL:
        result = new AnnotatedNullType((NullType) type, atypeFactory);
        break;
      case TYPEVAR:
        result = new AnnotatedTypeVariable((TypeVariable) type, atypeFactory, isDeclaration);
        break;
      case WILDCARD:
        result = new AnnotatedWildcardType((WildcardType) type, atypeFactory);
        break;
      case INTERSECTION:
        result = new AnnotatedIntersectionType((IntersectionType) type, atypeFactory);
        break;
      case UNION:
        result = new AnnotatedUnionType((UnionType) type, atypeFactory);
        break;
      default:
        if (type.getKind().isPrimitive()) {
          result = new AnnotatedPrimitiveType((PrimitiveType) type, atypeFactory);
          break;
        }
        throw new BugInCF(
            "AnnotatedTypeMirror.createType: unidentified type "
                + type
                + " ("
                + type.getKind()
                + ")");
    }
    /*if (jctype.isAnnotated()) {
        result.addAnnotations(jctype.getAnnotationMirrors());
    }*/
    return result;
  }

  protected static final EqualityAtmComparer EQUALITY_COMPARER = new EqualityAtmComparer();
  protected static final HashcodeAtmVisitor HASHCODE_VISITOR = new HashcodeAtmVisitor();

  /** The factory to use for lazily creating annotated types. */
  protected final AnnotatedTypeFactory atypeFactory;

  /** Actual type wrapped with this AnnotatedTypeMirror. */
  protected final TypeMirror underlyingType;

  /**
   * Saves the result of {@code underlyingType.toString().hashcode()} to use when computing the hash
   * code of this. (Because AnnotatedTypeMirrors are mutable, the hash code for this cannot be
   * saved.) Call {@link #getUnderlyingTypeHashCode()} rather than using the field directly.
   */
  private int underlyingTypeHashCode = -1;

  /** The annotations on this type. */
  // AnnotationMirror doesn't override Object.hashCode, .equals, so we use
  // the class name of Annotation instead.
  // Caution: Assumes that a type can have at most one AnnotationMirror for any Annotation type.
  protected final Set<AnnotationMirror> annotations = AnnotationUtils.createAnnotationSet();

  /** The explicitly written annotations on this type. */
  // TODO: use this to cache the result once computed? For generic types?
  // protected final Set<AnnotationMirror> explicitannotations =
  // AnnotationUtils.createAnnotationSet();

  /**
   * Constructor for AnnotatedTypeMirror.
   *
   * @param underlyingType the underlying type
   * @param atypeFactory used to create further types and to access global information (Types,
   *     Elements, ...)
   */
  private AnnotatedTypeMirror(TypeMirror underlyingType, AnnotatedTypeFactory atypeFactory) {
    this.underlyingType = underlyingType;
    assert atypeFactory != null;
    this.atypeFactory = atypeFactory;
  }

  @Override
  public final boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (!(o instanceof AnnotatedTypeMirror)) {
      return false;
    }

    return EQUALITY_COMPARER.visit(this, (AnnotatedTypeMirror) o, null);
  }

  @Pure
  @Override
  public final int hashCode() {
    return HASHCODE_VISITOR.visit(this);
  }

  /**
   * Applies a visitor to this type.
   *
   * @param <R> the return type of the visitor's methods
   * @param <P> the type of the additional parameter to the visitor's methods
   * @param v the visitor operating on this type
   * @param p additional parameter to the visitor
   * @return a visitor-specified result
   */
  public abstract <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p);

  /**
   * Returns the {@code kind} of this type.
   *
   * @return the kind of this type
   */
  public TypeKind getKind() {
    return underlyingType.getKind();
  }

  /**
   * Given a primitive type, return its kind. Given a boxed primitive type, return the corresponding
   * primitive type kind. Otherwise, return null.
   *
   * @return a primitive type kind if this is a primitive type or boxed primitive type; otherwise
   *     null
   */
  public TypeKind getPrimitiveKind() {
    return TypeKindUtils.primitiveOrBoxedToTypeKind(getUnderlyingType());
  }

  /**
   * Returns the underlying unannotated Java type, which this wraps.
   *
   * @return the underlying type
   */
  public TypeMirror getUnderlyingType() {
    return underlyingType;
  }

  /**
   * Returns true if this type mirror represents a declaration, rather than a use, of a type.
   *
   * <p>For example, {@code class List<T> { ... }} declares a new type {@code List<T>}, while {@code
   * List<Integer>} is a use of the type.
   *
   * @return true if this represents a declaration
   */
  public boolean isDeclaration() {
    return false;
  }

  public AnnotatedTypeMirror asUse() {
    return this;
  }

  /**
   * Returns true if an annotation from the given sub-hierarchy targets this type.
   *
   * <p>It doesn't account for annotations in deep types (type arguments, array components, etc).
   *
   * @param p the qualifier hierarchy to check for
   * @return true iff an annotation from the same hierarchy as p is present
   */
  public boolean isAnnotatedInHierarchy(AnnotationMirror p) {
    return getAnnotationInHierarchy(p) != null;
  }

  /**
   * Returns an annotation from the given sub-hierarchy, if such an annotation targets this type;
   * otherwise returns null.
   *
   * <p>It doesn't account for annotations in deep types (type arguments, array components, etc).
   *
   * <p>If there is only one hierarchy, you can use {@link #getAnnotation()} instead.
   *
   * <p>May return null if the receiver is a type variable or a wildcard without a primary
   * annotation, or if the receiver is not yet fully annotated.
   *
   * @param p the qualifier hierarchy to check for
   * @return an annotation from the same hierarchy as p if present
   */
  public AnnotationMirror getAnnotationInHierarchy(AnnotationMirror p) {
    AnnotationMirror aliased = p;
    if (!atypeFactory.isSupportedQualifier(aliased)) {
      aliased = atypeFactory.canonicalAnnotation(p);
    }
    if (atypeFactory.isSupportedQualifier(aliased)) {
      QualifierHierarchy qualHier = this.atypeFactory.getQualifierHierarchy();
      AnnotationMirror anno = qualHier.findAnnotationInSameHierarchy(annotations, aliased);
      if (anno != null) {
        return anno;
      }
    }
    return null;
  }

  /**
   * Returns an annotation from the given sub-hierarchy, if such an annotation is present on this
   * type or on its extends bounds; otherwise returns null.
   *
   * <p>It doesn't account for annotations in deep types (type arguments, array components, etc).
   *
   * @param p the qualifier hierarchy to check for
   * @return an annotation from the same hierarchy as p if present
   */
  public AnnotationMirror getEffectiveAnnotationInHierarchy(AnnotationMirror p) {
    AnnotationMirror aliased = p;
    if (!atypeFactory.isSupportedQualifier(aliased)) {
      aliased = atypeFactory.canonicalAnnotation(p);
    }
    if (atypeFactory.isSupportedQualifier(aliased)) {
      QualifierHierarchy qualHier = this.atypeFactory.getQualifierHierarchy();
      AnnotationMirror anno =
          qualHier.findAnnotationInSameHierarchy(getEffectiveAnnotations(), aliased);
      if (anno != null) {
        return anno;
      }
    }
    return null;
  }

  /**
   * Returns the annotations on this type. It does not include annotations in deep types (type
   * arguments, array components, etc).
   *
   * <p>To get the single annotation in a particular hierarchy, use {@link
   * #getAnnotationInHierarchy}. If there is only one hierarchy, you can use {@link #getAnnotation}.
   *
   * @return a unmodifiable set of the annotations on this
   */
  public final Set<AnnotationMirror> getAnnotations() {
    return Collections.unmodifiableSet(annotations);
  }

  /**
   * Returns the annotations on this type; mutations affect this object, because the return type is
   * an alias of the {@code annotations} field. It does not include annotations in deep types (type
   * arguments, array components, etc).
   *
   * <p>The returned set should not be modified, but for efficiency reasons modification is not
   * prevented. Modifications might break invariants.
   *
   * @return the set of the annotations on this; mutations affect this object
   */
  protected final Set<AnnotationMirror> getAnnotationsField() {
    return annotations;
  }

  /**
   * Returns the single annotation on this type. It does not include annotations in deep types (type
   * arguments, array components, etc).
   *
   * <p>This method requires that there is only a single hierarchy. In that case, it is equivalent
   * to {@link #getAnnotationInHierarchy}.
   *
   * @see #getAnnotations
   * @return the annotation on this, or null if none (which can only happen if {@code this} is a
   *     type variable or wildcard)
   */
  public final @Nullable AnnotationMirror getAnnotation() {
    if (annotations.isEmpty()) {
      // This AnnotatedTypeMirror must be a type variable or wildcard.
      return null;
    }
    if (annotations.size() != 1) {
      throw new BugInCF("Bad annotation size for getAnnotation(): " + this);
    }
    return annotations.iterator().next();
  }

  /**
   * Returns the "effective" annotations on this type, i.e. the annotations on the type itself, or
   * on the upper/extends bound of a type variable/wildcard (recursively, until a class type is
   * reached).
   *
   * @return a set of the annotations on this
   */
  public Set<AnnotationMirror> getEffectiveAnnotations() {
    Set<AnnotationMirror> effectiveAnnotations = getErased().getAnnotations();
    //        assert atypeFactory.qualHierarchy.getWidth() == effectiveAnnotations
    //                .size() : "Invalid number of effective annotations ("
    //                + effectiveAnnotations + "). Should be "
    //                + atypeFactory.qualHierarchy.getWidth() + " but is "
    //                + effectiveAnnotations.size() + ". Type: " + this;
    return effectiveAnnotations;
  }

  /**
   * Returns the actual annotation mirror used to annotate this type, whose Class equals the passed
   * annoClass if one exists, null otherwise.
   *
   * @param annoClass annotation class
   * @return the annotation mirror for anno
   */
  public AnnotationMirror getAnnotation(Class<? extends Annotation> annoClass) {
    for (AnnotationMirror annoMirror : annotations) {
      if (atypeFactory.areSameByClass(annoMirror, annoClass)) {
        return annoMirror;
      }
    }
    return null;
  }

  /**
   * Returns the actual annotation mirror used to annotate this type, whose name equals the passed
   * {@code annoName} if one exists, null otherwise.
   *
   * @param annoName annotation name
   * @return the annotation mirror for annoName
   */
  public AnnotationMirror getAnnotation(String annoName) {
    for (AnnotationMirror annoMirror : annotations) {
      if (AnnotationUtils.areSameByName(annoMirror, annoName)) {
        return annoMirror;
      }
    }
    return null;
  }

  /**
   * Returns the set of explicitly written annotations on this type that are supported by this
   * checker. This is useful to check the validity of annotations explicitly present on a type, as
   * flow inference might add annotations that were not previously present. Note that since
   * AnnotatedTypeMirror instances are created for type uses, this method will return explicit
   * annotations in type use locations but will not return explicit annotations that had an impact
   * on defaulting, such as an explicit annotation on a class declaration. For example, given:
   *
   * <p>{@code @MyExplicitAnno class MyClass {}; MyClass myClassInstance; }
   *
   * <p>the result of calling {@code
   * atypeFactory.getAnnotatedType(variableTreeForMyClassInstance).getExplicitAnnotations()}
   *
   * <p>will not contain {@code @MyExplicitAnno}.
   *
   * @return the set of explicitly written annotations on this type that are supported by this
   *     checker
   */
  public Set<AnnotationMirror> getExplicitAnnotations() {
    // TODO JSR 308: The explicit type annotations should be always present
    Set<AnnotationMirror> explicitAnnotations = AnnotationUtils.createAnnotationSet();
    List<? extends AnnotationMirror> typeAnnotations =
        this.getUnderlyingType().getAnnotationMirrors();

    for (AnnotationMirror explicitAnno : typeAnnotations) {
      if (atypeFactory.isSupportedQualifier(explicitAnno)) {
        explicitAnnotations.add(explicitAnno);
      }
    }

    return explicitAnnotations;
  }

  /**
   * Determines whether this type contains the given annotation. This method considers the
   * annotation's values, that is, if the type is "@A("s") @B(3) Object" a call with "@A("t") or
   * "@A" will return false, whereas a call with "@B(3)" will return true.
   *
   * <p>In contrast to {@link #hasAnnotationRelaxed(AnnotationMirror)} this method also compares
   * annotation values.
   *
   * @param a the annotation to check for
   * @return true iff the type contains the annotation {@code a}
   * @see #hasAnnotationRelaxed(AnnotationMirror)
   */
  public boolean hasAnnotation(AnnotationMirror a) {
    return AnnotationUtils.containsSame(annotations, a);
  }

  /**
   * Determines whether this type contains an annotation with the same annotation type as a
   * particular annotation. This method does not consider an annotation's values.
   *
   * @param a the class of annotation to check for
   * @return true iff the type contains an annotation with the same type as the annotation given by
   *     {@code a}
   */
  public boolean hasAnnotation(Class<? extends Annotation> a) {
    return getAnnotation(a) != null;
  }

  /**
   * Returns the actual effective annotation mirror used to annotate this type, whose Class equals
   * the passed annoClass if one exists, null otherwise.
   *
   * @param annoClass annotation class
   * @return the annotation mirror for anno
   */
  public AnnotationMirror getEffectiveAnnotation(Class<? extends Annotation> annoClass) {
    for (AnnotationMirror annoMirror : getEffectiveAnnotations()) {
      if (atypeFactory.areSameByClass(annoMirror, annoClass)) {
        return annoMirror;
      }
    }
    return null;
  }

  /**
   * A version of hasAnnotation that considers annotations on the upper bound of wildcards and type
   * variables.
   *
   * @see #hasAnnotation(Class)
   */
  public boolean hasEffectiveAnnotation(Class<? extends Annotation> a) {
    return getEffectiveAnnotation(a) != null;
  }

  /**
   * A version of hasAnnotation that considers annotations on the upper bound of wildcards and type
   * variables.
   *
   * @see #hasAnnotation(AnnotationMirror)
   */
  public boolean hasEffectiveAnnotation(AnnotationMirror a) {
    return AnnotationUtils.containsSame(getEffectiveAnnotations(), a);
  }

  /**
   * Determines whether this type contains the given annotation explicitly written at declaration.
   * This method considers the annotation's values, that is, if the type is {@code @A("s") @B(3)
   * Object}, a call with {@code @A("t")} or {@code @A} will return false, whereas a call with
   * {@code @B(3)} will return true.
   *
   * <p>In contrast to {@link #hasExplicitAnnotationRelaxed(AnnotationMirror)} this method also
   * compares annotation values.
   *
   * <p>See the documentation for {@link #getExplicitAnnotations()} for details on which explicit
   * annotations are not included.
   *
   * @param a the annotation to check for
   * @return true iff the annotation {@code a} is explicitly written on the type
   * @see #hasExplicitAnnotationRelaxed(AnnotationMirror)
   * @see #getExplicitAnnotations()
   */
  public boolean hasExplicitAnnotation(AnnotationMirror a) {
    return AnnotationUtils.containsSame(getExplicitAnnotations(), a);
  }

  /**
   * Determines whether this type contains an annotation with the same annotation type as a
   * particular annotation. This method does not consider an annotation's values, that is, if the
   * type is "@A("s") @B(3) Object" a call with "@A("t"), "@A", or "@B" will return true.
   *
   * @param a the annotation to check for
   * @return true iff the type contains an annotation with the same type as the annotation given by
   *     {@code a}
   * @see #hasAnnotation(AnnotationMirror)
   */
  public boolean hasAnnotationRelaxed(AnnotationMirror a) {
    return AnnotationUtils.containsSameByName(annotations, a);
  }

  /**
   * A version of hasAnnotationRelaxed that considers annotations on the upper bound of wildcards
   * and type variables.
   *
   * @see #hasAnnotationRelaxed(AnnotationMirror)
   */
  public boolean hasEffectiveAnnotationRelaxed(AnnotationMirror a) {
    return AnnotationUtils.containsSameByName(getEffectiveAnnotations(), a);
  }

  /**
   * A version of hasAnnotationRelaxed that only considers annotations that are explicitly written
   * on the type.
   *
   * <p>See the documentation for {@link #getExplicitAnnotations()} for details on which explicit
   * annotations are not included.
   *
   * @see #hasAnnotationRelaxed(AnnotationMirror)
   * @see #getExplicitAnnotations()
   */
  public boolean hasExplicitAnnotationRelaxed(AnnotationMirror a) {
    return AnnotationUtils.containsSameByName(getExplicitAnnotations(), a);
  }

  /**
   * Determines whether this type contains an explicitly written annotation with the same annotation
   * type as a particular annotation. This method does not consider an annotation's values.
   *
   * <p>See the documentation for {@link #getExplicitAnnotations()} for details on which explicit
   * annotations are not included.
   *
   * @param a the class of annotation to check for
   * @return true iff the type contains an explicitly written annotation with the same type as the
   *     annotation given by {@code a}
   * @see #getExplicitAnnotations()
   */
  public boolean hasExplicitAnnotation(Class<? extends Annotation> a) {
    return AnnotationUtils.containsSameByName(getExplicitAnnotations(), getAnnotation(a));
  }

  /**
   * Adds an annotation to this type. Only annotations supported by the type factory are added.
   *
   * @param a the annotation to add
   */
  public void addAnnotation(AnnotationMirror a) {
    if (a == null) {
      throw new BugInCF("AnnotatedTypeMirror.addAnnotation: null argument.");
    }
    if (atypeFactory.isSupportedQualifier(a)) {
      this.annotations.add(a);
    } else {
      AnnotationMirror aliased = atypeFactory.canonicalAnnotation(a);
      if (atypeFactory.isSupportedQualifier(aliased)) {
        addAnnotation(aliased);
      }
    }
  }

  /**
   * Adds an annotation to this type, removing any existing annotation from the same qualifier
   * hierarchy first.
   *
   * @param a the annotation to add
   */
  public void replaceAnnotation(AnnotationMirror a) {
    this.removeAnnotationInHierarchy(a);
    this.addAnnotation(a);
  }

  /**
   * Adds an annotation to this type.
   *
   * @param a the class of the annotation to add
   */
  public void addAnnotation(Class<? extends Annotation> a) {
    AnnotationMirror anno = AnnotationBuilder.fromClass(atypeFactory.elements, a);
    addAnnotation(anno);
  }

  /**
   * Adds multiple annotations to this type.
   *
   * @param annotations the annotations to add
   */
  public void addAnnotations(Iterable<? extends AnnotationMirror> annotations) {
    for (AnnotationMirror a : annotations) {
      this.addAnnotation(a);
    }
  }

  /**
   * Adds each of the given annotations to the current type, only if no annotation from the same
   * qualifier hierarchy is present.
   *
   * @param annotations the annotations to add
   */
  public void addMissingAnnotations(Iterable<? extends AnnotationMirror> annotations) {
    for (AnnotationMirror a : annotations) {
      if (!this.isAnnotatedInHierarchy(a)) {
        this.addAnnotation(a);
      }
    }
  }

  /**
   * Adds multiple annotations to this type, removing any existing annotations from the same
   * qualifier hierarchy first.
   *
   * @param replAnnos the annotations to replace
   */
  public void replaceAnnotations(Iterable<? extends AnnotationMirror> replAnnos) {
    for (AnnotationMirror a : replAnnos) {
      this.replaceAnnotation(a);
    }
  }

  /**
   * Removes an annotation from the type.
   *
   * @param a the annotation to remove
   * @return true if the annotation was removed, false if the type's annotations were unchanged
   */
  public boolean removeAnnotation(AnnotationMirror a) {
    AnnotationMirror anno = AnnotationUtils.getSame(annotations, a);
    if (anno != null) {
      return annotations.remove(anno);
    }
    return false;
  }

  /**
   * Removes an annotation of the given class from the type.
   *
   * @param a the class of the annotation to remove
   * @return true if the annotation was removed, false if the type's annotations were unchanged
   */
  public boolean removeAnnotationByClass(Class<? extends Annotation> a) {
    AnnotationMirror anno = atypeFactory.getAnnotationByClass(annotations, a);
    if (anno != null) {
      return annotations.remove(anno);
    }
    return false;
  }

  /**
   * Remove any annotation that is in the same qualifier hierarchy as the parameter.
   *
   * @param a an annotation from the same qualifier hierarchy
   * @return if an annotation was removed
   */
  public boolean removeAnnotationInHierarchy(AnnotationMirror a) {
    AnnotationMirror prev = this.getAnnotationInHierarchy(a);
    if (prev != null) {
      return this.removeAnnotation(prev);
    }
    return false;
  }

  /**
   * Remove an annotation that is in the same qualifier hierarchy as the parameter, unless it's the
   * top annotation.
   *
   * @param a an annotation from the same qualifier hierarchy
   * @return if an annotation was removed
   */
  public boolean removeNonTopAnnotationInHierarchy(AnnotationMirror a) {
    AnnotationMirror prev = this.getAnnotationInHierarchy(a);
    QualifierHierarchy qualHier = this.atypeFactory.getQualifierHierarchy();
    if (prev != null && !prev.equals(qualHier.getTopAnnotation(a))) {
      return this.removeAnnotation(prev);
    }
    return false;
  }

  /**
   * Removes multiple annotations from the type.
   *
   * @param annotations the annotations to remove
   * @return true if at least one annotation was removed, false if the type's annotations were
   *     unchanged
   */
  public boolean removeAnnotations(Iterable<? extends AnnotationMirror> annotations) {
    boolean changed = false;
    for (AnnotationMirror a : annotations) {
      changed |= this.removeAnnotation(a);
    }
    return changed;
  }

  /**
   * Removes all primary annotations on this type. Make sure to add an annotation after calling
   * this.
   *
   * <p>This method should only be used in very specific situations. For individual type systems, it
   * is generally better to use {@link #removeAnnotation(AnnotationMirror)} and similar methods.
   */
  public void clearAnnotations() {
    annotations.clear();
  }

  @SideEffectFree
  @Override
  public final String toString() {
    return atypeFactory.getAnnotatedTypeFormatter().format(this);
  }

  @SideEffectFree
  public final String toString(boolean verbose) {
    return atypeFactory.getAnnotatedTypeFormatter().format(this, verbose);
  }

  /**
   * Returns the erasure type of the this type, according to JLS specifications.
   *
   * @see <a
   *     href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.6">https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.6</a>
   * @return the erasure of this AnnotatedTypeMirror, this is always a copy even if the erasure and
   *     the original type are equivalent
   */
  public AnnotatedTypeMirror getErased() {
    return deepCopy();
  }

  /**
   * Returns a deep copy of this type. A deep copy implies that each component type is copied
   * recursively and the returned type refers to those copies in its component locations.
   *
   * <p>Note: deepCopy provides two important properties in the returned copy:
   *
   * <ol>
   *   <li>Structure preservation -- The exact structure of the original AnnotatedTypeMirror is
   *       preserved in the copy including all component types.
   *   <li>Annotation preservation -- All of the annotations from the original AnnotatedTypeMirror
   *       and its components have been copied to the new type.
   * </ol>
   *
   * If copyAnnotations is set to false, the second property, Annotation preservation, is removed.
   * This is useful for cases in which the user may want to copy the structure of a type exactly but
   * NOT its annotations.
   *
   * @return a deep copy
   */
  public abstract AnnotatedTypeMirror deepCopy(final boolean copyAnnotations);

  /**
   * Returns a deep copy of this type with annotations.
   *
   * <p>Each subclass implements this method with the subclass return type. The method body must
   * always be a call to deepCopy(true).
   *
   * @return a deep copy of this type with annotations
   * @see #deepCopy(boolean)
   */
  public abstract AnnotatedTypeMirror deepCopy();

  /**
   * Returns a shallow copy of this type. A shallow copy implies that each component type in the
   * output copy refers to the same object as the object being copied.
   *
   * @param copyAnnotations whether copy should have annotations, i.e. whether field {@code
   *     annotations} should be copied.
   */
  public abstract AnnotatedTypeMirror shallowCopy(boolean copyAnnotations);

  /**
   * Returns a shallow copy of this type with annotations.
   *
   * <p>Each subclass implements this method with the subclass return type. The method body must
   * always be a call to shallowCopy(true).
   *
   * @see #shallowCopy(boolean)
   * @return a shallow copy of this type with annotations
   */
  public abstract AnnotatedTypeMirror shallowCopy();

  /**
   * Returns whether this type or any component type is a wildcard type for which Java 7 type
   * inference is insufficient. See issue 979, or the documentation on AnnotatedWildcardType.
   *
   * @return whether this type or any component type is a wildcard type for which Java 7 type
   *     inference is insufficient
   */
  public boolean containsUninferredTypeArguments() {
    return atypeFactory.containsUninferredTypeArguments(this);
  }

  /**
   * Create an {@link AnnotatedDeclaredType} with the underlying type of {@link Object}. It includes
   * any annotations placed by {@link AnnotatedTypeFactory#fromElement(Element)}.
   *
   * @param atypeFactory type factory to use
   * @return AnnotatedDeclaredType for Object
   */
  protected static AnnotatedDeclaredType createTypeOfObject(AnnotatedTypeFactory atypeFactory) {
    AnnotatedDeclaredType objectType =
        atypeFactory.fromElement(
            atypeFactory.elements.getTypeElement(Object.class.getCanonicalName()));
    objectType.declaration = false;
    return objectType;
  }

  /**
   * Returns the result of calling {@code underlyingType.toString().hashcode()}. This method saves
   * the result in a field so that it isn't recomputed each time.
   *
   * @return the result of calling {@code underlyingType.toString().hashcode()}
   */
  public int getUnderlyingTypeHashCode() {
    if (underlyingTypeHashCode == -1) {
      underlyingTypeHashCode = underlyingType.toString().hashCode();
    }
    return underlyingTypeHashCode;
  }

  /** Represents a declared type (whether class or interface). */
  public static class AnnotatedDeclaredType extends AnnotatedTypeMirror {

    /** Parametrized Type Arguments. */
    protected List<AnnotatedTypeMirror> typeArgs;

    /**
     * Whether the type was initially raw, i.e. the user did not provide the type arguments.
     * typeArgs will contain inferred type arguments, which might be too conservative at the moment.
     * TODO: improve inference.
     *
     * <p>Ideally, the field would be final. However, when we determine the supertype of a raw type,
     * we need to set wasRaw for the supertype.
     */
    private boolean wasRaw;

    /** The enclosing type. May be null. */
    protected @Nullable AnnotatedDeclaredType enclosingType;

    /** True if this represents a declaration, rather than a use, of a type. */
    private boolean declaration;

    /**
     * Constructor for this type. The result contains no annotations.
     *
     * @param type underlying kind of this type
     * @param atypeFactory the AnnotatedTypeFactory used to create this type
     */
    private AnnotatedDeclaredType(
        DeclaredType type, AnnotatedTypeFactory atypeFactory, boolean declaration) {
      super(type, atypeFactory);
      TypeElement typeelem = (TypeElement) type.asElement();
      DeclaredType declty = (DeclaredType) typeelem.asType();
      wasRaw = !declty.getTypeArguments().isEmpty() && type.getTypeArguments().isEmpty();

      TypeMirror encl = type.getEnclosingType();
      if (encl.getKind() == TypeKind.DECLARED) {
        this.enclosingType = (AnnotatedDeclaredType) createType(encl, atypeFactory, declaration);
      } else if (encl.getKind() == TypeKind.NONE) {
        this.enclosingType = null;
      } else {
        throw new BugInCF(
            "AnnotatedDeclaredType: unsupported enclosing type: "
                + type.getEnclosingType()
                + " ("
                + encl.getKind()
                + ")");
      }

      this.declaration = declaration;
    }

    @Override
    public boolean isDeclaration() {
      return declaration;
    }

    @Override
    public AnnotatedDeclaredType deepCopy(boolean copyAnnotations) {
      return (AnnotatedDeclaredType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedDeclaredType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedDeclaredType asUse() {
      if (!this.isDeclaration()) {
        return this;
      }
      AnnotatedDeclaredType result = this.shallowCopy(true);
      result.declaration = false;
      // setTypeArguments calls asUse on all the new type arguments.
      result.setTypeArguments(typeArgs);

      return result;
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitDeclared(this, p);
    }

    /**
     * Sets the type arguments on this type.
     *
     * @param ts the type arguments
     */
    // WMD
    public void setTypeArguments(List<? extends AnnotatedTypeMirror> ts) {
      if (ts == null || ts.isEmpty()) {
        typeArgs = Collections.emptyList();
      } else {
        if (isDeclaration()) {
          // TODO: check that all args are really declarations
          typeArgs = Collections.unmodifiableList(ts);
        } else {
          List<AnnotatedTypeMirror> uses = CollectionsPlume.mapList(AnnotatedTypeMirror::asUse, ts);
          typeArgs = Collections.unmodifiableList(uses);
        }
      }
    }

    /**
     * Returns the type argument for this type.
     *
     * @return the type argument for this type
     */
    public List<AnnotatedTypeMirror> getTypeArguments() {
      if (typeArgs != null) {
        return typeArgs;
      } else if (wasRaw()) {
        // Initialize the type arguments with uninferred wildcards.
        BoundsInitializer.initializeTypeArgs(this);
        return typeArgs;
      } else if (getUnderlyingType().getTypeArguments().isEmpty()) {
        typeArgs = Collections.emptyList();
        return typeArgs;
      } else {
        // Initialize type argument for a non-raw declared type that has type arguments/
        BoundsInitializer.initializeTypeArgs(this);
        return typeArgs;
      }
    }

    /**
     * Returns true if the type was raw, that is, type arguments were not provided but instead
     * inferred.
     *
     * @return true iff the type was raw
     */
    public boolean wasRaw() {
      return wasRaw;
    }

    /**
     * Set the wasRaw flag to true. This should only be necessary when determining the supertypes of
     * a raw type.
     */
    protected void setWasRaw() {
      this.wasRaw = true;
    }

    @Override
    public DeclaredType getUnderlyingType() {
      return (DeclaredType) underlyingType;
    }

    @Override
    public List<AnnotatedDeclaredType> directSupertypes() {
      return Collections.unmodifiableList(SupertypeFinder.directSupertypes(this));
    }

    @Override
    public AnnotatedDeclaredType shallowCopy() {
      return shallowCopy(true);
    }

    @Override
    public AnnotatedDeclaredType shallowCopy(boolean copyAnnotations) {
      AnnotatedDeclaredType type =
          new AnnotatedDeclaredType(getUnderlyingType(), atypeFactory, declaration);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      type.setEnclosingType(getEnclosingType());
      type.setTypeArguments(getTypeArguments());
      return type;
    }

    /**
     * Return the declared type with its type arguments removed. This also replaces the underlying
     * type with its erasure.
     *
     * @return a fresh copy of the declared type with no type arguments
     */
    @Override
    public AnnotatedDeclaredType getErased() {
      AnnotatedDeclaredType erased =
          (AnnotatedDeclaredType)
              AnnotatedTypeMirror.createType(
                  atypeFactory.types.erasure(underlyingType), atypeFactory, declaration);
      erased.addAnnotations(this.getAnnotations());
      AnnotatedDeclaredType erasedEnclosing = erased.getEnclosingType();
      AnnotatedDeclaredType thisEnclosing = this.getEnclosingType();
      while (erasedEnclosing != null) {
        erasedEnclosing.addAnnotations(thisEnclosing.getAnnotations());
        erasedEnclosing = erasedEnclosing.getEnclosingType();
        thisEnclosing = thisEnclosing.getEnclosingType();
      }
      return erased;
    }

    /**
     * Sets the enclosing type.
     *
     * @param enclosingType the new enclosing type
     */
    /*default-visibility*/ void setEnclosingType(@Nullable AnnotatedDeclaredType enclosingType) {
      this.enclosingType = enclosingType;
    }

    /**
     * Returns the enclosing type, as in the type of {@code A} in the type {@code A.B}. May return
     * null.
     *
     * @return enclosingType the enclosing type, or null if this is a top-level type
     */
    public @Nullable AnnotatedDeclaredType getEnclosingType() {
      return enclosingType;
    }
  }

  /** Represents a type of an executable. An executable is a method, constructor, or initializer. */
  public static class AnnotatedExecutableType extends AnnotatedTypeMirror {

    private ExecutableElement element;

    private AnnotatedExecutableType(ExecutableType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    protected final List<AnnotatedTypeMirror> paramTypes = new ArrayList<>();
    protected AnnotatedDeclaredType receiverType;
    protected AnnotatedTypeMirror returnType;
    protected final List<AnnotatedTypeMirror> throwsTypes = new ArrayList<>();
    protected final List<AnnotatedTypeVariable> typeVarTypes = new ArrayList<>();

    /**
     * Returns true if this type represents a varargs method.
     *
     * @return true if this type represents a varargs method
     */
    public boolean isVarArgs() {
      return this.element.isVarArgs();
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitExecutable(this, p);
    }

    @Override
    public ExecutableType getUnderlyingType() {
      return (ExecutableType) this.underlyingType;
    }

    /**
     * It never makes sense to add annotations to an executable type - instead, they should be added
     * to the right component.
     */
    @Override
    public void addAnnotation(AnnotationMirror a) {
      assert false : "AnnotatedExecutableType.addAnnotation should never be called";
    }

    /**
     * Sets the parameter types of this executable type, excluding the receiver.
     *
     * @param params the parameter types, excluding the receiver
     */
    void setParameterTypes(List<? extends AnnotatedTypeMirror> params) {
      paramTypes.clear();
      paramTypes.addAll(params);
    }

    /**
     * Returns the parameter types of this executable type, excluding the receiver.
     *
     * @return the parameter types of this executable type, excluding the receiver
     */
    public List<AnnotatedTypeMirror> getParameterTypes() {
      if (paramTypes.isEmpty()
          && !((ExecutableType) underlyingType).getParameterTypes().isEmpty()) { // lazy init
        for (TypeMirror t : ((ExecutableType) underlyingType).getParameterTypes()) {
          paramTypes.add(createType(t, atypeFactory, false));
        }
      }
      return Collections.unmodifiableList(paramTypes);
    }

    /**
     * Sets the return type of this executable type.
     *
     * @param returnType the return type
     */
    void setReturnType(AnnotatedTypeMirror returnType) {
      this.returnType = returnType;
    }

    /**
     * The return type of a method or constructor. For constructors, the return type is not VOID,
     * but the type of the enclosing class.
     *
     * @return the return type of this executable type
     */
    public AnnotatedTypeMirror getReturnType() {
      if (returnType == null
          && element != null
          && ((ExecutableType) underlyingType).getReturnType() != null) { // lazy init
        TypeMirror aret = ((ExecutableType) underlyingType).getReturnType();
        if (aret.getKind() == TypeKind.ERROR) {
          // Maybe the input is uncompilable, or maybe the type is not completed yet (see Issue
          // #244).
          throw new ErrorTypeKindException(
              "Problem with return type of %s.%s: %s [%s %s]",
              element, element.getEnclosingElement(), aret, aret.getKind(), aret.getClass());
        }
        if (((MethodSymbol) element).isConstructor()) {
          // For constructors, the underlying return type is void.
          // Take the type of the enclosing class instead.
          aret = element.getEnclosingElement().asType();
          if (aret.getKind() == TypeKind.ERROR) {
            throw new ErrorTypeKindException(
                "Input is not compilable; problem with constructor %s return type: %s [%s %s]"
                    + " (enclosing element = %s [%s])",
                element,
                aret,
                aret.getKind(),
                aret.getClass(),
                element.getEnclosingElement(),
                element.getEnclosingElement().getClass());
          }
        }
        returnType = createType(aret, atypeFactory, false);
      }
      return returnType;
    }

    /**
     * Sets the receiver type on this executable type.
     *
     * @param receiverType the receiver type
     */
    void setReceiverType(AnnotatedDeclaredType receiverType) {
      this.receiverType = receiverType;
    }

    /**
     * Returns the receiver type of this executable type; null for static methods and constructors
     * of top-level classes.
     *
     * @return the receiver type of this executable type; null for static methods and constructors
     *     of top-level classes
     */
    public @Nullable AnnotatedDeclaredType getReceiverType() {
      if (receiverType == null && ElementUtils.hasReceiver(getElement())) {

        TypeElement encl = ElementUtils.enclosingTypeElement(getElement());
        if (getElement().getKind() == ElementKind.CONSTRUCTOR) {
          // Can only reach this branch if we're the constructor of a nested class
          encl = ElementUtils.enclosingTypeElement(encl.getEnclosingElement());
        }
        AnnotatedTypeMirror type = createType(encl.asType(), atypeFactory, false);
        assert type instanceof AnnotatedDeclaredType;
        receiverType = (AnnotatedDeclaredType) type;
      }
      return receiverType;
    }

    /**
     * Sets the thrown types of this executable type.
     *
     * @param thrownTypes the thrown types
     */
    void setThrownTypes(List<? extends AnnotatedTypeMirror> thrownTypes) {
      this.throwsTypes.clear();
      this.throwsTypes.addAll(thrownTypes);
    }

    /**
     * Returns the thrown types of this executable type.
     *
     * @return the thrown types of this executable type
     */
    public List<AnnotatedTypeMirror> getThrownTypes() {
      if (throwsTypes.isEmpty()
          && !((ExecutableType) underlyingType).getThrownTypes().isEmpty()) { // lazy init
        for (TypeMirror t : ((ExecutableType) underlyingType).getThrownTypes()) {
          throwsTypes.add(createType(t, atypeFactory, false));
        }
      }
      return Collections.unmodifiableList(throwsTypes);
    }

    /**
     * Sets the type variables associated with this executable type.
     *
     * @param types the type variables of this executable type
     */
    void setTypeVariables(List<AnnotatedTypeVariable> types) {
      typeVarTypes.clear();
      typeVarTypes.addAll(types);
    }

    /**
     * Returns the type variables of this executable type, if any.
     *
     * @return the type variables of this executable type, if any
     */
    public List<AnnotatedTypeVariable> getTypeVariables() {
      if (typeVarTypes.isEmpty()
          && !((ExecutableType) underlyingType).getTypeVariables().isEmpty()) { // lazy init
        for (TypeMirror t : ((ExecutableType) underlyingType).getTypeVariables()) {
          typeVarTypes.add((AnnotatedTypeVariable) createType(t, atypeFactory, true));
        }
      }
      return Collections.unmodifiableList(typeVarTypes);
    }

    @Override
    public AnnotatedExecutableType deepCopy(boolean copyAnnotations) {
      return (AnnotatedExecutableType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedExecutableType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedExecutableType shallowCopy(boolean copyAnnotations) {
      AnnotatedExecutableType type = new AnnotatedExecutableType(getUnderlyingType(), atypeFactory);

      type.setElement(getElement());
      type.setParameterTypes(getParameterTypes());
      type.setReceiverType(getReceiverType());
      type.setReturnType(getReturnType());
      type.setThrownTypes(getThrownTypes());
      type.setTypeVariables(getTypeVariables());

      return type;
    }

    @Override
    public AnnotatedExecutableType shallowCopy() {
      return shallowCopy(true);
    }

    public @NonNull ExecutableElement getElement() {
      return element;
    }

    public void setElement(@NonNull ExecutableElement elem) {
      this.element = elem;
    }

    @Override
    public AnnotatedExecutableType getErased() {
      AnnotatedExecutableType type =
          new AnnotatedExecutableType(
              (ExecutableType) atypeFactory.types.erasure(getUnderlyingType()), atypeFactory);
      type.setElement(getElement());
      type.setParameterTypes(erasureList(getParameterTypes()));
      if (getReceiverType() != null) {
        type.setReceiverType(getReceiverType().getErased());
      } else {
        type.setReceiverType(null);
      }
      type.setReturnType(getReturnType().getErased());
      type.setThrownTypes(erasureList(getThrownTypes()));

      return type;
    }

    /**
     * Returns the erased types corresponding to the given types.
     *
     * @param lst annotated type mirrors
     * @return erased annotated type mirrors
     */
    private List<AnnotatedTypeMirror> erasureList(Iterable<? extends AnnotatedTypeMirror> lst) {
      return CollectionsPlume.mapList(AnnotatedTypeMirror::getErased, lst);
    }
  }

  /**
   * Represents Array types in java. A multidimensional array type is represented as an array type
   * whose component type is also an array type.
   */
  public static class AnnotatedArrayType extends AnnotatedTypeMirror {

    private AnnotatedArrayType(ArrayType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    /** The component type of this array type. */
    private AnnotatedTypeMirror componentType;

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitArray(this, p);
    }

    @Override
    public ArrayType getUnderlyingType() {
      return (ArrayType) this.underlyingType;
    }

    /**
     * Sets the component type of this array.
     *
     * @param type the component type
     */
    // WMD
    public void setComponentType(AnnotatedTypeMirror type) {
      this.componentType = type;
    }

    /**
     * Returns the component type of this array.
     *
     * @return the component type of this array
     */
    public AnnotatedTypeMirror getComponentType() {
      if (componentType == null) { // lazy init
        setComponentType(
            createType(((ArrayType) underlyingType).getComponentType(), atypeFactory, false));
      }
      return componentType;
    }

    @Override
    public AnnotatedArrayType deepCopy(boolean copyAnnotations) {
      return (AnnotatedArrayType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedArrayType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedArrayType shallowCopy(boolean copyAnnotations) {
      AnnotatedArrayType type = new AnnotatedArrayType((ArrayType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      type.setComponentType(getComponentType());
      return type;
    }

    @Override
    public AnnotatedArrayType shallowCopy() {
      return shallowCopy(true);
    }

    @Override
    public AnnotatedArrayType getErased() {
      // IMPORTANT NOTE: The returned type is a fresh Object because
      // the componentType is the only component of arrays and the
      // call to getErased will return a fresh object.
      // | T[ ] | = |T| [ ]
      AnnotatedArrayType at = shallowCopy();
      AnnotatedTypeMirror ct = at.getComponentType().getErased();
      at.setComponentType(ct);
      return at;
    }
  }

  /**
   * Throw an exception if the boundType is null or a declaration.
   *
   * @param boundDescription the variety of bound: "Lower", "Super", or "Extends"
   * @param boundType the type being tested
   * @param thisType the object for which boundType is a bound
   */
  private static void checkBound(
      String boundDescription, AnnotatedTypeMirror boundType, AnnotatedTypeMirror thisType) {
    if (boundType == null || boundType.isDeclaration()) {
      throw new BugInCF(
          "%s bounds should never be null or a declaration.%n  new bound = %s%n  type = %s",
          boundDescription, boundType, thisType);
    }
  }

  /**
   * Represents a type variable. A type variable may be explicitly declared by a type parameter of a
   * type, method, or constructor. A type variable may also be declared implicitly, as by the
   * capture conversion of a wildcard type argument (see chapter 5 of The Java Language
   * Specification, Third Edition).
   */
  public static class AnnotatedTypeVariable extends AnnotatedTypeMirror {

    private AnnotatedTypeVariable(
        TypeVariable type, AnnotatedTypeFactory atypeFactory, boolean declaration) {
      super(type, atypeFactory);
      this.declaration = declaration;
    }

    /** The lower bound of the type variable. */
    private AnnotatedTypeMirror lowerBound;

    /** The upper bound of the type variable. */
    private AnnotatedTypeMirror upperBound;

    private boolean declaration;

    @Override
    public boolean isDeclaration() {
      return declaration;
    }

    @Override
    public void addAnnotation(AnnotationMirror a) {
      super.addAnnotation(a);
      fixupBoundAnnotations();
    }

    /**
     * Change whether this {@code AnnotatedTypeVariable} is considered a use or a declaration (use
     * this method with caution).
     *
     * @param declaration true if this type variable should be considered a declaration
     */
    public void setDeclaration(boolean declaration) {
      this.declaration = declaration;
    }

    @Override
    public AnnotatedTypeVariable asUse() {
      if (!this.isDeclaration()) {
        return this;
      }

      AnnotatedTypeVariable result = this.shallowCopy();
      result.declaration = false;

      return result;
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitTypeVariable(this, p);
    }

    @Override
    public TypeVariable getUnderlyingType() {
      return (TypeVariable) this.underlyingType;
    }

    /**
     * Set the lower bound of this variable type.
     *
     * <p>Returns the lower bound of this type variable. While a type parameter cannot include an
     * explicit lower bound declaration, capture conversion can produce a type variable with a
     * non-trivial lower bound. Type variables otherwise have a lower bound of NullType.
     *
     * @param type the lower bound type
     */
    void setLowerBound(AnnotatedTypeMirror type) {
      checkBound("Lower", type, this);
      this.lowerBound = type;
      fixupBoundAnnotations();
    }

    /**
     * Get the lower bound field directly, bypassing any lazy initialization. This method is
     * necessary to prevent infinite recursions in initialization. In general, prefer getLowerBound.
     *
     * @return the lower bound field
     */
    public AnnotatedTypeMirror getLowerBoundField() {
      return lowerBound;
    }

    /**
     * Returns the lower bound type of this type variable.
     *
     * @return the lower bound type of this type variable
     */
    public AnnotatedTypeMirror getLowerBound() {
      if (lowerBound == null) { // lazy init
        BoundsInitializer.initializeBounds(this);
        fixupBoundAnnotations();
      }
      return lowerBound;
    }

    // If the lower bound was not present in underlyingType, then its annotation was defaulted from
    // the AnnotatedTypeFactory.  If the lower bound annotation is a supertype of the upper bound
    // annotation, then the type is ill-formed.  In that case, change the defaulted lower bound to
    // be consistent with the explicitly-written upper bound.
    //
    // As a concrete example, if the default annotation is @Nullable, then the type "X extends
    // @NonNull Y" should not be converted into "X extends @NonNull Y super @Nullable bottomtype"
    // but be converted into "X extends @NonNull Y super @NonNull bottomtype".
    //
    // In addition, ensure consistency of annotations on type variables
    // and the upper bound. Assume class C<X extends @Nullable Object>.
    // The type of "@Nullable X" has to be "@Nullable X extends @Nullable Object",
    // because otherwise the annotations are inconsistent.
    private void fixupBoundAnnotations() {
      if (!this.getAnnotationsField().isEmpty()) {
        Set<AnnotationMirror> newAnnos = this.getAnnotationsField();
        if (upperBound != null) {
          upperBound.replaceAnnotations(newAnnos);
        }

        // Note:
        // if the lower bound is a type variable
        // then when we place annotations on the primary annotation
        //   this will actually cause the type variable to be exact and propagate the primary
        //   annotation to the type variable because primary annotations overwrite the upper and
        //   lower bounds of type variables when getUpperBound/getLowerBound is called
        if (lowerBound != null) {
          lowerBound.replaceAnnotations(newAnnos);
        }
      }
    }

    /**
     * Set the upper bound of this variable type.
     *
     * @param type the upper bound type
     */
    void setUpperBound(AnnotatedTypeMirror type) {
      checkBound("Upper", type, this);
      this.upperBound = type;
      fixupBoundAnnotations();
    }

    /**
     * Get the upper bound field directly, bypassing any lazy initialization. This method is
     * necessary to prevent infinite recursions in initialization. In general, prefer getUpperBound.
     *
     * @return the upper bound field
     */
    public AnnotatedTypeMirror getUpperBoundField() {
      return upperBound;
    }

    /**
     * Get the upper bound of the type variable, possibly lazily initializing it. Attention: If the
     * upper bound is lazily initialized, it will not contain any annotations! Callers of the method
     * have to make sure that an AnnotatedTypeFactory first processed the bound.
     *
     * @return the upper bound type of this type variable
     */
    public AnnotatedTypeMirror getUpperBound() {
      if (upperBound == null) { // lazy init
        BoundsInitializer.initializeBounds(this);
        fixupBoundAnnotations();
      }
      return upperBound;
    }

    public AnnotatedTypeParameterBounds getBounds() {
      return new AnnotatedTypeParameterBounds(getUpperBound(), getLowerBound());
    }

    public AnnotatedTypeParameterBounds getBoundFields() {
      return new AnnotatedTypeParameterBounds(getUpperBoundField(), getLowerBoundField());
    }

    /** Used to terminate recursion into upper bounds. */
    private boolean inUpperBounds = false;

    @Override
    public AnnotatedTypeVariable deepCopy(boolean copyAnnotations) {
      return (AnnotatedTypeVariable) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedTypeVariable deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedTypeVariable shallowCopy(boolean copyAnnotations) {
      AnnotatedTypeVariable type =
          new AnnotatedTypeVariable(((TypeVariable) underlyingType), atypeFactory, declaration);

      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }

      if (!inUpperBounds) {
        inUpperBounds = true;
        type.inUpperBounds = true;
        type.setUpperBound(getUpperBound().shallowCopy());
        inUpperBounds = false;
        type.inUpperBounds = false;
      }

      type.setLowerBound(getLowerBound().shallowCopy());

      return type;
    }

    @Override
    public AnnotatedTypeVariable shallowCopy() {
      return shallowCopy(true);
    }

    /**
     * This method will traverse the upper bound of this type variable calling getErased until it
     * finds the concrete upper bound. e.g.
     *
     * <pre>{@code  <E extends T>, T extends S, S extends List<String>>}</pre>
     *
     * A call to getErased will return the type List
     *
     * @return the erasure of the upper bound of this type
     *     <p>IMPORTANT NOTE: getErased should always return a FRESH object. This will occur for
     *     type variables if all other getErased methods are implemented appropriately. Therefore,
     *     to avoid extra copy calls, this method will not call deepCopy on getUpperBound
     */
    @Override
    public AnnotatedTypeMirror getErased() {
      // |T extends A&B| = |A|
      return this.getUpperBound().getErased();
    }
  }

  /**
   * A pseudo-type used where no actual type is appropriate. The kinds of NoType are:
   *
   * <ul>
   *   <li>VOID -- corresponds to the keyword void.
   *   <li>PACKAGE -- the pseudo-type of a package element.
   *   <li>NONE -- used in other cases where no actual type is appropriate; for example, the
   *       superclass of java.lang.Object.
   * </ul>
   */
  public static class AnnotatedNoType extends AnnotatedTypeMirror {

    private AnnotatedNoType(NoType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    // No need for methods
    // Might like to override annotate(), include(), execlude()
    // AS NoType does not accept any annotations

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitNoType(this, p);
    }

    @Override
    public NoType getUnderlyingType() {
      return (NoType) this.underlyingType;
    }

    @Override
    public AnnotatedNoType deepCopy(boolean copyAnnotations) {
      return (AnnotatedNoType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedNoType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedNoType shallowCopy(boolean copyAnnotations) {
      AnnotatedNoType type = new AnnotatedNoType((NoType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      return type;
    }

    @Override
    public AnnotatedNoType shallowCopy() {
      return shallowCopy(true);
    }
  }

  /** Represents the null type. This is the type of the expression {@code null}. */
  public static class AnnotatedNullType extends AnnotatedTypeMirror {

    private AnnotatedNullType(NullType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitNull(this, p);
    }

    @Override
    public NullType getUnderlyingType() {
      return (NullType) this.underlyingType;
    }

    @Override
    public AnnotatedNullType deepCopy(boolean copyAnnotations) {
      return (AnnotatedNullType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedNullType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedNullType shallowCopy(boolean copyAnnotations) {
      AnnotatedNullType type = new AnnotatedNullType((NullType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      return type;
    }

    @Override
    public AnnotatedNullType shallowCopy() {
      return shallowCopy(true);
    }
  }

  /**
   * Represents a primitive type. These include {@code boolean}, {@code byte}, {@code short}, {@code
   * int}, {@code long}, {@code char}, {@code float}, and {@code double}.
   */
  public static class AnnotatedPrimitiveType extends AnnotatedTypeMirror {

    private AnnotatedPrimitiveType(PrimitiveType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitPrimitive(this, p);
    }

    @Override
    public PrimitiveType getUnderlyingType() {
      return (PrimitiveType) this.underlyingType;
    }

    @Override
    public AnnotatedPrimitiveType deepCopy(boolean copyAnnotations) {
      return (AnnotatedPrimitiveType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedPrimitiveType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedPrimitiveType shallowCopy(boolean copyAnnotations) {
      AnnotatedPrimitiveType type =
          new AnnotatedPrimitiveType((PrimitiveType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      return type;
    }

    @Override
    public AnnotatedPrimitiveType shallowCopy() {
      return shallowCopy(true);
    }
  }

  /**
   * Represents a wildcard type argument. Examples include:
   *
   * <p>? ? extends Number ? super T
   *
   * <p>A wildcard may have its upper bound explicitly set by an extends clause, its lower bound
   * explicitly set by a super clause, or neither (but not both).
   */
  public static class AnnotatedWildcardType extends AnnotatedTypeMirror {
    /** Lower ({@code super}) bound. */
    private AnnotatedTypeMirror superBound;

    /** Upper ({@code extends} bound. */
    private AnnotatedTypeMirror extendsBound;

    /**
     * The type variable to which this wildcard is an argument. Used to initialize the upper bound
     * of unbounded wildcards and wildcards in raw types.
     */
    private TypeVariable typeVariable = null;

    private AnnotatedWildcardType(WildcardType type, AnnotatedTypeFactory factory) {
      super(type, factory);
    }

    @Override
    public void addAnnotation(AnnotationMirror a) {
      super.addAnnotation(a);
      fixupBoundAnnotations();
    }

    /**
     * Sets the super bound of this wildcard.
     *
     * @param type the type of the lower bound
     */
    void setSuperBound(AnnotatedTypeMirror type) {
      checkBound("Super", type, this);
      this.superBound = type;
      fixupBoundAnnotations();
    }

    public AnnotatedTypeMirror getSuperBoundField() {
      return superBound;
    }

    /**
     * Returns the lower bound of this wildcard. If no lower bound is explicitly declared, returns
     * {@code null}.
     *
     * @return the lower bound of this wildcard, or null if none is explicitly declared
     */
    public AnnotatedTypeMirror getSuperBound() {
      if (superBound == null) {
        BoundsInitializer.initializeSuperBound(this);
        fixupBoundAnnotations();
      }
      return this.superBound;
    }

    /**
     * Sets the upper bound of this wildcard.
     *
     * @param type the type of the upper bound
     */
    void setExtendsBound(AnnotatedTypeMirror type) {
      checkBound("Extends", type, this);
      this.extendsBound = type;
      fixupBoundAnnotations();
    }

    public AnnotatedTypeMirror getExtendsBoundField() {
      return extendsBound;
    }

    /**
     * Returns the upper bound of this wildcard. If no upper bound is explicitly declared, returns
     * the upper bound of the type variable to which the wildcard is bound.
     *
     * @return the upper bound of this wildcard. If no upper bound is explicitly declared, returns
     *     the upper bound of the type variable to which the wildcard is bound.
     */
    public AnnotatedTypeMirror getExtendsBound() {
      if (extendsBound == null) {
        BoundsInitializer.initializeExtendsBound(this);
        fixupBoundAnnotations();
      }
      return this.extendsBound;
    }

    private void fixupBoundAnnotations() {
      if (!this.getAnnotationsField().isEmpty()) {
        if (superBound != null) {
          superBound.replaceAnnotations(this.getAnnotationsField());
        }
        if (extendsBound != null) {
          extendsBound.replaceAnnotations(this.getAnnotationsField());
        }
      }
    }

    /**
     * Sets type variable to which this wildcard is an argument. This method should only be called
     * during initialization of the type.
     */
    void setTypeVariable(TypeParameterElement typeParameterElement) {
      this.typeVariable = (TypeVariable) typeParameterElement.asType();
    }

    /**
     * Sets type variable to which this wildcard is an argument. This method should only be called
     * during initialization of the type.
     */
    void setTypeVariable(TypeVariable typeVariable) {
      this.typeVariable = typeVariable;
    }

    /**
     * Returns the type variable to which this wildcard is an argument. Used to initialize the upper
     * bound of unbounded wildcards and wildcards in raw types.
     *
     * @return the type variable to which this wildcard is an argument
     */
    public TypeVariable getTypeVariable() {
      return typeVariable;
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitWildcard(this, p);
    }

    @Override
    public WildcardType getUnderlyingType() {
      return (WildcardType) this.underlyingType;
    }

    @Override
    public AnnotatedWildcardType deepCopy(boolean copyAnnotations) {
      return (AnnotatedWildcardType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedWildcardType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedWildcardType shallowCopy(boolean copyAnnotations) {
      AnnotatedWildcardType type =
          new AnnotatedWildcardType((WildcardType) underlyingType, atypeFactory);
      type.setExtendsBound(getExtendsBound().shallowCopy());
      type.setSuperBound(getSuperBound().shallowCopy());
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }

      type.uninferredTypeArgument = uninferredTypeArgument;
      type.typeVariable = typeVariable;

      return type;
    }

    @Override
    public AnnotatedWildcardType shallowCopy() {
      return shallowCopy(true);
    }

    /**
     * @see
     *     org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable#getErased()
     */
    @Override
    public AnnotatedTypeMirror getErased() {
      // |? extends A&B| = |A|
      return getExtendsBound().getErased();
    }

    // Remove the uninferredTypeArgument once method type
    // argument inference and raw type handling is improved.
    private boolean uninferredTypeArgument = false;

    /**
     * Set that this wildcard is from an uninferred type argument. This method should only be used
     * within the framework. Once issues that depend on this hack, in particular Issue 979, are
     * fixed, this must be removed.
     */
    public void setUninferredTypeArgument() {
      uninferredTypeArgument = true;
    }

    /**
     * Returns whether or not this wildcard is a type argument for which inference failed to infer a
     * type.
     *
     * @return true if this wildcard is a type argument for which inference failed
     */
    public boolean isUninferredTypeArgument() {
      return uninferredTypeArgument;
    }
  }

  /**
   * Represents an intersection type.
   *
   * <p>For example: {@code MyObject & Serializable & Comparable<MyObject>}
   */
  public static class AnnotatedIntersectionType extends AnnotatedTypeMirror {

    /** A list of the bounds of this which are also its direct super types. */
    protected List<AnnotatedTypeMirror> bounds;

    /**
     * Creates an {@code AnnotatedIntersectionType} with the underlying type {@code type}. The
     * result contains no annotations.
     *
     * @param type underlying kind of this type
     * @param atypeFactory the factory used to construct this intersection type
     */
    private AnnotatedIntersectionType(IntersectionType type, AnnotatedTypeFactory atypeFactory) {
      super(type, atypeFactory);
    }

    /**
     * {@inheritDoc}
     *
     * <p>Also, copies {@code a} to all the bounds.
     *
     * @param a the annotation to add
     */
    @Override
    public void addAnnotation(AnnotationMirror a) {
      super.addAnnotation(a);
      fixupBoundAnnotations();
    }

    /**
     * Copies {@link #annotations} to all the bounds, replacing any existing annotations in the same
     * hierarchy.
     */
    private void fixupBoundAnnotations() {
      if (!this.getAnnotationsField().isEmpty()) {
        Set<AnnotationMirror> newAnnos = this.getAnnotationsField();
        if (bounds != null) {
          for (AnnotatedTypeMirror bound : bounds) {
            if (bound.getKind() != TypeKind.TYPEVAR) {
              bound.replaceAnnotations(newAnnos);
            }
          }
        }
      }
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitIntersection(this, p);
    }

    @Override
    public IntersectionType getUnderlyingType() {
      return (IntersectionType) super.getUnderlyingType();
    }

    @Override
    public AnnotatedIntersectionType deepCopy(boolean copyAnnotations) {
      return (AnnotatedIntersectionType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedIntersectionType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedIntersectionType shallowCopy(boolean copyAnnotations) {
      AnnotatedIntersectionType type =
          new AnnotatedIntersectionType((IntersectionType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      type.bounds = this.bounds;
      return type;
    }

    @Override
    public AnnotatedIntersectionType shallowCopy() {
      return shallowCopy(true);
    }

    /**
     * {@inheritDoc}
     *
     * <p>This returns the same types as {@link #getBounds()}.
     *
     * @return the direct super types of this
     */
    @Override
    public List<? extends AnnotatedTypeMirror> directSupertypes() {
      return getBounds();
    }

    /**
     * This returns the bounds of the intersection type. Although only declared types can appear in
     * an explicitly written intersections, during capture conversion, intersections with other
     * kinds of types are created.
     *
     * <p>This returns the same types as {@link #directSupertypes()}.
     *
     * @return the bounds of this, which are also the direct super types of this
     */
    public List<AnnotatedTypeMirror> getBounds() {
      if (bounds == null) {
        List<? extends TypeMirror> ubounds = ((IntersectionType) underlyingType).getBounds();
        List<AnnotatedTypeMirror> res =
            CollectionsPlume.mapList(
                (TypeMirror bnd) -> createType(bnd, atypeFactory, false), ubounds);
        bounds = Collections.unmodifiableList(res);
        fixupBoundAnnotations();
      }
      return bounds;
    }

    /**
     * Sets the bounds.
     *
     * @param bounds bounds to use
     */
    /*default-visibility*/ void setBounds(List<AnnotatedTypeMirror> bounds) {
      this.bounds = bounds;
    }

    /**
     * Copy the first annotation (in each hierarchy) on a bound to the primary annotation location
     * of the intersection type.
     *
     * <p>For example, in the type {@code @NonNull Object & @Initialized @Nullable Serializable},
     * {@code @Nullable} and {@code @Initialized} are copied to the primary annotation location.
     */
    public void copyIntersectionBoundAnnotations() {
      Set<AnnotationMirror> annos = AnnotationUtils.createAnnotationSet();
      for (AnnotatedTypeMirror bound : getBounds()) {
        for (AnnotationMirror a : bound.getAnnotations()) {
          if (atypeFactory.getQualifierHierarchy().findAnnotationInSameHierarchy(annos, a)
              == null) {
            annos.add(a);
          }
        }
      }
      addAnnotations(annos);
    }
  }

  // TODO: Ensure union types are handled everywhere.
  // TODO: Should field "annotations" contain anything?
  public static class AnnotatedUnionType extends AnnotatedTypeMirror {

    /**
     * Creates a new AnnotatedUnionType.
     *
     * @param type underlying kind of this type
     * @param atypeFactory type factory
     */
    private AnnotatedUnionType(UnionType type, AnnotatedTypeFactory atypeFactory) {
      super(type, atypeFactory);
    }

    @Override
    public <R, P> R accept(AnnotatedTypeVisitor<R, P> v, P p) {
      return v.visitUnion(this, p);
    }

    @Override
    public AnnotatedUnionType deepCopy(boolean copyAnnotations) {
      return (AnnotatedUnionType) new AnnotatedTypeCopier(copyAnnotations).visit(this);
    }

    @Override
    public AnnotatedUnionType deepCopy() {
      return deepCopy(true);
    }

    @Override
    public AnnotatedUnionType shallowCopy(boolean copyAnnotations) {
      AnnotatedUnionType type = new AnnotatedUnionType((UnionType) underlyingType, atypeFactory);
      if (copyAnnotations) {
        type.addAnnotations(this.getAnnotationsField());
      }
      type.alternatives = this.alternatives;
      return type;
    }

    @Override
    public AnnotatedUnionType shallowCopy() {
      return shallowCopy(true);
    }

    /** The types that are unioned to form this AnnotatedUnionType. */
    protected List<AnnotatedDeclaredType> alternatives;

    /**
     * Returns the types that are unioned to form this AnnotatedUnionType.
     *
     * @return the types that are unioned to form this AnnotatedUnionType
     */
    public List<AnnotatedDeclaredType> getAlternatives() {
      if (alternatives == null) {
        List<? extends TypeMirror> ualts = ((UnionType) underlyingType).getAlternatives();
        List<AnnotatedDeclaredType> res =
            CollectionsPlume.mapList(
                (TypeMirror alt) -> (AnnotatedDeclaredType) createType(alt, atypeFactory, false),
                ualts);
        alternatives = Collections.unmodifiableList(res);
      }
      return alternatives;
    }
  }

  /**
   * This method returns a list of AnnotatedTypeMirrors where the Java type of each ATM is an
   * immediate supertype (class or interface) of the Java type of this. The interface types, if any,
   * appear at the end of the list. If the directSuperType has type arguments, then the annotations
   * on those type arguments are taken with proper translation from the declaration of the Java type
   * of this.
   *
   * <p>For example,
   *
   * <pre>
   * {@code class B<T> { ... } }
   * {@code class A extends B<@NonNull String> { ... } }
   * {@code @Nullable A a;}
   * </pre>
   *
   * The direct supertype of the ATM {@code @Nullable A} is {@code @Nullable B<@NonNull String>}.
   *
   * <p>An example with more complex type arguments:
   *
   * <pre>
   * {@code class D<Q,R> { ... } }
   * {@code class A<T,S> extends D<S,T> { ... } }
   * {@code @Nullable A<@NonNull String, @NonNull Object> a;}
   * </pre>
   *
   * The direct supertype of the ATM {@code @Nullable A<@NonNull String, @NonNull Object>} is
   * {@code @Nullable B<@NonNull Object, @NonNull String>}.
   *
   * <p>An example with more than one direct supertype:
   *
   * <pre>
   * {@code class B<T> implements List<Integer> { ... } }
   * {@code class A extends B<@NonNull String> implements List<Integer> { ... } }
   * {@code @Nullable A a;}
   * </pre>
   *
   * The direct supertypes of the ATM {@code @Nullable A} are {@code @Nullable B <@NonNull String>}
   * and {@code @Nullable List<@NonNull Integer>}.
   *
   * @return the immediate supertypes of this
   * @see Types#directSupertypes(TypeMirror)
   */
  public List<? extends AnnotatedTypeMirror> directSupertypes() {
    return SupertypeFinder.directSupertypes(this);
  }
}
