package org.checkerframework.framework.type;

import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.WildcardType;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNoType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeVisitor;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TypeAnnotationUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.StringsPlume;

/**
 * BoundsInitializer creates AnnotatedTypeMirrors (without annotations) for the bounds of type
 * variables and wildcards. Its static helper methods are called from AnnotatedTypeMirror. When an
 * initializer method is called for a particular bound, the entirety of that bound, including
 * circular references, will be created.
 */
public class BoundsInitializer {
  // ============================================================================================
  // Static helper methods called from AnnotatedTypeMirror to initialize bounds of wildcards or
  // type variables
  // ============================================================================================

  /**
   * Initializes the type arguments of {@code declaredType}. The upper bound of unbound wildcards is
   * set to the upper bound of the type parameter for which it is an argument. If {@code
   * declaredType} is raw, then the type arguments are uninferred wildcards.
   *
   * @param declaredType type whose arguments are initialized
   */
  public static void initializeTypeArgs(AnnotatedDeclaredType declaredType) {
    final DeclaredType underlyingType = (DeclaredType) declaredType.underlyingType;
    if (underlyingType.getTypeArguments().isEmpty() && !declaredType.wasRaw()) {
      // No type arguments to infer.
      return;
    }

    final TypeElement typeElement =
        (TypeElement) declaredType.atypeFactory.types.asElement(underlyingType);
    int numTypeParameters = typeElement.getTypeParameters().size();
    final List<AnnotatedTypeMirror> typeArgs = new ArrayList<>(numTypeParameters);

    // Create AnnotatedTypeMirror for each type argument and store them in the typeArgsMap.
    // Take un-annotated type variables as the key for this map.
    Map<TypeVariable, AnnotatedTypeMirror> typeArgMap = new HashMap<>(numTypeParameters);
    for (int i = 0; i < numTypeParameters; i++) {
      TypeMirror javaTypeArg;
      if (declaredType.wasRaw()) {
        TypeVariable typeVariable = (TypeVariable) typeElement.getTypeParameters().get(i).asType();
        javaTypeArg = getUpperBoundAsWildcard(typeVariable, declaredType.atypeFactory);
      } else {
        javaTypeArg = declaredType.getUnderlyingType().getTypeArguments().get(i);
      }

      final AnnotatedTypeMirror typeArg =
          AnnotatedTypeMirror.createType(javaTypeArg, declaredType.atypeFactory, false);
      if (typeArg.getKind() == TypeKind.WILDCARD) {
        AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) typeArg;
        wildcardType.setTypeVariable(typeElement.getTypeParameters().get(i));
        if (declaredType.wasRaw()) {
          wildcardType.setUninferredTypeArgument();
        }
      }
      typeArgs.add(typeArg);

      // Add mapping from type parameter to the annotated type argument.
      TypeVariable key =
          (TypeVariable)
              TypeAnnotationUtils.unannotatedType(typeElement.getTypeParameters().get(i).asType());
      typeArgMap.put(key, typeArg);

      if (javaTypeArg.getKind() == TypeKind.TYPEVAR) {
        // Add mapping from Java type argument to the annotated type argument.
        key = (TypeVariable) TypeAnnotationUtils.unannotatedType(javaTypeArg);
        typeArgMap.put(key, typeArg);
      }
    }

    // Initialize type argument bounds using the typeArgsMap.
    for (AnnotatedTypeMirror typeArg : typeArgs) {
      switch (typeArg.getKind()) {
        case WILDCARD:
          AnnotatedWildcardType wildcardType = (AnnotatedWildcardType) typeArg;
          initializeExtendsBound(wildcardType, typeArgMap);
          initializeSuperBound(wildcardType, typeArgMap);
          break;
        case TYPEVAR:
          initializeBounds((AnnotatedTypeVariable) typeArg, typeArgMap);
          break;
        default:
          // do nothing
      }
    }
    declaredType.typeArgs = Collections.unmodifiableList(typeArgs);
  }

  /**
   * Returns a wildcard whose upper bound is the same as {@code typeVariable}. If the upper bound is
   * an intersection, then this method returns an unbound wildcard.
   */
  private static WildcardType getUpperBoundAsWildcard(
      TypeVariable typeVariable, AnnotatedTypeFactory factory) {
    TypeMirror upperBound = typeVariable.getUpperBound();
    switch (upperBound.getKind()) {
      case ARRAY:
      case DECLARED:
      case TYPEVAR:
        return factory.types.getWildcardType(upperBound, null);
      case INTERSECTION:
        // Can't create a wildcard with an intersection as the upper bound, so use
        // an unbound wildcard instead.  The extends bound of the
        // AnnotatedWildcardType will be initialized properly by this class.
        return factory.types.getWildcardType(null, null);
      default:
        throw new BugInCF(
            "Unexpected upper bound kind: %s type: %s", upperBound.getKind(), upperBound);
    }
  }

  /**
   * Create the entire lower bound and upper bound, with no missing information, for typeVar. If a
   * typeVar is recursive the appropriate cycles will be introduced in the type
   *
   * @param typeVar the type variable whose lower bound is being initialized
   */
  public static void initializeBounds(final AnnotatedTypeVariable typeVar) {
    initializeBounds(typeVar, null);
  }

  /**
   * Create the entire lower bound and upper bound, with no missing information, for typeVar. If a
   * typeVar is recursive the appropriate cycles will be introduced in the type
   *
   * @param typeVar the type variable whose lower bound is being initialized
   * @param map a mapping of type parameters to type arguments. May be null.
   */
  private static void initializeBounds(
      final AnnotatedTypeVariable typeVar, Map<TypeVariable, AnnotatedTypeMirror> map) {
    final Set<AnnotationMirror> annos = saveAnnotations(typeVar);

    InitializerVisitor visitor = new InitializerVisitor(new TypeVariableStructure(typeVar), map);
    visitor.initializeLowerBound(typeVar);
    visitor.resolveTypeVarReferences(typeVar);

    InitializerVisitor visitor2 = new InitializerVisitor(new TypeVariableStructure(typeVar), map);
    visitor2.initializeUpperBound(typeVar);
    visitor2.resolveTypeVarReferences(typeVar);

    restoreAnnotations(typeVar, annos);
  }

  /**
   * If we are initializing a type variable with a primary annotation than we should first
   * initialize it as if it were a declaration (i.e. as if it had no primary annotations) and then
   * apply the primary annotations. We do this so that when we make copies of the original type to
   * represent recursive references the recursive references don't have the primary annotation.
   *
   * <pre>{@code
   * e.g.   given the declaration {@code <E extends List<E>>}
   *        if we do not do this, the NonNull on the use @NonNull E
   *        would be copied to the primary annotation on E in the bound {@code List<E>}
   *        i.e. the use would be {@code <@NonNull E extends @NonNull List<@NonNull E>>}
   *             rather than      {@code <@NonNull E extends @NonNull List<E>>}
   * }</pre>
   */
  private static Set<AnnotationMirror> saveAnnotations(final AnnotatedTypeMirror type) {
    if (!type.getAnnotationsField().isEmpty()) {
      final Set<AnnotationMirror> annos = new HashSet<>(type.getAnnotations());
      type.clearAnnotations();
      return annos;
    }

    return null;
  }

  private static void restoreAnnotations(
      final AnnotatedTypeMirror type, final Set<AnnotationMirror> annos) {
    if (annos != null) {
      type.addAnnotations(annos);
    }
  }

  /**
   * Create the entire super bound, with no missing information, for wildcard. If a wildcard is
   * recursive the appropriate cycles will be introduced in the type
   *
   * @param wildcard the wildcard whose lower bound is being initialized
   */
  public static void initializeSuperBound(final AnnotatedWildcardType wildcard) {
    initializeSuperBound(wildcard, null);
  }

  /**
   * Create the entire super bound, with no missing information, for wildcard. If a wildcard is
   * recursive the appropriate cycles will be introduced in the type
   *
   * @param wildcard the wildcard whose lower bound is being initialized
   * @param map a mapping of type parameters to type arguments. May be null.
   */
  private static void initializeSuperBound(
      final AnnotatedWildcardType wildcard, Map<TypeVariable, AnnotatedTypeMirror> map) {
    final Set<AnnotationMirror> annos = saveAnnotations(wildcard);

    InitializerVisitor visitor = new InitializerVisitor(new RecursiveTypeStructure(), map);
    visitor.initializeSuperBound(wildcard);
    visitor.resolveTypeVarReferences(wildcard);

    restoreAnnotations(wildcard, annos);
  }

  /**
   * Create the entire extends bound, with no missing information, for wildcard. If a wildcard is
   * recursive the appropriate cycles will be introduced in the type
   *
   * @param wildcard the wildcard whose extends bound is being initialized
   */
  public static void initializeExtendsBound(final AnnotatedWildcardType wildcard) {
    initializeExtendsBound(wildcard, null);
  }

  /**
   * Create the entire extends bound, with no missing information, for wildcard. If a wildcard is
   * recursive the appropriate cycles will be introduced in the type
   *
   * @param wildcard the wildcard whose extends bound is being initialized
   * @param map a mapping of type parameters to type arguments. May be null.
   */
  private static void initializeExtendsBound(
      final AnnotatedWildcardType wildcard, Map<TypeVariable, AnnotatedTypeMirror> map) {
    final Set<AnnotationMirror> annos = saveAnnotations(wildcard);
    InitializerVisitor visitor = new InitializerVisitor(new RecursiveTypeStructure(), map);
    visitor.initializeExtendsBound(wildcard);
    visitor.resolveTypeVarReferences(wildcard);
    restoreAnnotations(wildcard, annos);
  }

  // ============================================================================================
  // Classes and methods used to make the above static helper methods work
  // ============================================================================================

  /**
   * Creates the AnnotatedTypeMirrors (without annotations) for the bounds of all type variables and
   * wildcards in a given type. If the type is recursive, {@code T extends Comparable<T>}, then all
   * references to the same type variable are references to the same AnnotatedTypeMirror.
   */
  private static class InitializerVisitor implements AnnotatedTypeVisitor<Void, Void> {
    /**
     * The {@link RecursiveTypeStructure} corresponding to the first wildcard or type variable bound
     * initialization that kicked this visitation off.
     */
    private final RecursiveTypeStructure topLevelStructure;

    /**
     * The {@link RecursiveTypeStructure} corresponding to the wildcard or type variable that is
     * currently being visited.
     */
    private RecursiveTypeStructure currentStructure;

    /** A mapping from TypeVariable to its {@link TypeVariableStructure}. */
    private final Map<TypeVariable, TypeVariableStructure> typeVarToStructure = new HashMap<>();

    /**
     * A mapping from WildcardType to its AnnotatedWildcardType. The first time this visitor
     * encounters a wildcard it creates an annotated type and adds it to this map. The next time the
     * wilcard is encounter, the annotated type in this map is returned.
     */
    private final Map<WildcardType, AnnotatedWildcardType> wildcards = new HashMap<>();

    /**
     * A mapping from IntersectionType to its AnnotatedIntersectionType. The first time this visitor
     * encounters an intersection it creates an annotated type and adds it to this map. The next
     * time the intersection is encounter, the annotated type in this map is returned.
     */
    private final Map<IntersectionType, AnnotatedIntersectionType> intersections = new HashMap<>();

    /**
     * Mapping from TypeVariable to AnnotatedTypeMirror. The annotated type mirror should be used
     * for any use of the type variable rather than creating and initializing a new annotated type.
     * This is used for type arguments that have already been initialized outside of this visitor.
     */
    private final Map<TypeVariable, AnnotatedTypeMirror> typevars;

    /**
     * Creates an InitializerVisitor.
     *
     * @param recursiveTypeStructure structure for the type being initialized
     * @param typevars a mapping from type variable to annotated types that have already been
     *     initialized
     */
    public InitializerVisitor(
        RecursiveTypeStructure recursiveTypeStructure,
        Map<TypeVariable, AnnotatedTypeMirror> typevars) {
      this.topLevelStructure = recursiveTypeStructure;
      this.currentStructure = recursiveTypeStructure;
      if (typevars != null) {
        this.typevars = typevars;
      } else {
        this.typevars = Collections.emptyMap();
      }
      if (recursiveTypeStructure instanceof TypeVariableStructure) {
        TypeVariableStructure typeVarStruct = (TypeVariableStructure) recursiveTypeStructure;
        typeVarToStructure.put(typeVarStruct.typeVar, typeVarStruct);
      }
    }

    // ----------------------------------------------------------------------------------------
    // Visit methods that keep track of the path traversed through type variable bounds, and the
    // wildcards/intersections that have been encountered.
    // ----------------------------------------------------------------------------------------

    @Override
    public Void visit(AnnotatedTypeMirror type) {
      type.accept(this, null);
      return null;
    }

    @Override
    public Void visit(AnnotatedTypeMirror type, Void aVoid) {
      visit(type);
      return null;
    }

    @Override
    public Void visitDeclared(AnnotatedDeclaredType type, Void aVoid) {
      initializeTypeArgs(type);
      if (type.enclosingType != null) {
        TypePathNode node = currentStructure.addPathNode(new EnclosingTypeNode());
        visit(type.enclosingType);
        currentStructure.removePathNode(node);
      }
      return null;
    }

    @Override
    public Void visitIntersection(AnnotatedIntersectionType type, Void aVoid) {

      if (intersections.containsKey(type.getUnderlyingType())) {
        return null;
      }

      intersections.put(type.getUnderlyingType(), type);

      List<AnnotatedTypeMirror> bounds = type.getBounds();
      for (int i = 0; i < bounds.size(); i++) {
        AnnotatedTypeMirror supertype = bounds.get(i);
        TypePathNode node = currentStructure.addPathNode(new IntersectionBoundNode(i));
        visit(supertype);
        currentStructure.removePathNode(node);
      }
      return null;
    }

    @Override
    public Void visitUnion(AnnotatedUnionType type, Void aVoid) {

      List<AnnotatedDeclaredType> alts = type.getAlternatives();
      for (int i = 0; i < alts.size(); i++) {
        AnnotatedDeclaredType alt = alts.get(i);
        TypePathNode node = currentStructure.addPathNode(new AlternativeTypeNode(i));
        visit(alt);
        currentStructure.removePathNode(node);
      }
      return null;
    }

    @Override
    public Void visitArray(AnnotatedArrayType type, Void aVoid) {
      if (!TypesUtils.isPrimitive(type.getComponentType().getUnderlyingType())) {
        // Only recur on component type if it's not a primitive.
        // Array component types are the only place a primitive is allowed in bounds
        TypePathNode componentNode = currentStructure.addPathNode(new ArrayComponentNode());
        type.setComponentType(getOrVisit(type.getComponentType()));
        currentStructure.removePathNode(componentNode);
      }
      return null;
    }

    @Override
    public Void visitTypeVariable(AnnotatedTypeVariable type, Void aVoid) {
      this.currentStructure.addTypeVar(type.getUnderlyingType());
      if (typeVarToStructure.containsKey(type.getUnderlyingType())) {
        return null;
      }
      TypeVariableStructure typeVarStruct = new TypeVariableStructure(type);
      typeVarToStructure.put(type.getUnderlyingType(), typeVarStruct);
      RecursiveTypeStructure parentStructure = this.currentStructure;

      this.currentStructure = typeVarStruct;
      initializeUpperBound(type);
      initializeLowerBound(type);
      this.currentStructure = parentStructure;

      return null;
    }

    @Override
    public Void visitNull(AnnotatedNullType type, Void aVoid) {
      return null;
    }

    @Override
    public Void visitWildcard(AnnotatedWildcardType wildcard, Void aVoid) {
      if (wildcard.getSuperBoundField() == null) {
        initializeSuperBound(wildcard);

      } else {
        throw new BugInCF(
            "Wildcard super field should not be initialized:%n"
                + "wildcard=%s%n"
                + "currentStructure=%s%n",
            wildcard, currentStructure);
      }

      if (wildcard.getExtendsBoundField() == null) {
        initializeExtendsBound(wildcard);
      } else {
        throw new BugInCF(
            "Wildcard extends field should not be initialized:%n"
                + "wildcard=%s%n"
                + "currentStructure=%s%n",
            wildcard, currentStructure);
      }

      return null;
    }

    @Override
    public Void visitPrimitive(AnnotatedPrimitiveType type, Void aVoid) {
      throw new BugInCF("Unexpected AnnotatedPrimitiveType " + type);
    }

    @Override
    public Void visitNoType(AnnotatedNoType type, Void aVoid) {
      throw new BugInCF("Unexpected AnnotatedNoType " + type);
    }

    @Override
    public Void visitExecutable(AnnotatedExecutableType type, Void aVoid) {
      throw new BugInCF("Unexpected AnnotatedExecutableType " + type);
    }

    /**
     * If the underlying type of {@code type} has been visited before, return the previous
     * AnnotatedTypeMirror. Otherwise, visit {@code type} and return it.
     *
     * @param type type to visit
     * @return {@code type} or an AnnotatedTypeMirror with the same underlying type that was
     *     previously visited.
     */
    public AnnotatedTypeMirror getOrVisit(AnnotatedTypeMirror type) {
      switch (type.getKind()) {
        case WILDCARD:
          AnnotatedWildcardType wildcard = (AnnotatedWildcardType) type;
          if (wildcards.containsKey(wildcard.getUnderlyingType())) {
            return wildcards.get(wildcard.getUnderlyingType());
          }
          break;
        case INTERSECTION:
          if (intersections.containsKey(type.getUnderlyingType())) {
            return intersections.get(type.getUnderlyingType());
          }
          break;
        case TYPEVAR:
          TypeVariable key =
              (TypeVariable) TypeAnnotationUtils.unannotatedType(type.getUnderlyingType());
          if (typevars.containsKey(key)) {
            return typevars.get(key);
          }
          break;
        default:
          // do nothing
      }
      visit(type);
      return type;
    }

    // ----------------------------------------------------------------------------------------
    //

    /**
     * Initialize {@code typeVar}'s upper bound.
     *
     * @param typeVar type variable whose upper bound is initialized
     */
    public void initializeUpperBound(AnnotatedTypeVariable typeVar) {
      AnnotatedTypeMirror upperBound = createAndSetUpperBound(typeVar);

      TypePathNode pathNode = new UpperBoundNode();
      currentStructure.addPathNode(pathNode);
      visit(upperBound);
      currentStructure.removePathNode(pathNode);
    }

    /**
     * Initialize {@code typeVar}'s lower bound.
     *
     * @param typeVar type variable whose lower bound is initialized
     */
    public void initializeLowerBound(AnnotatedTypeVariable typeVar) {
      AnnotatedTypeMirror lowerBound = createAndSetLowerBound(typeVar);

      TypePathNode pathNode = new LowerBoundNode();
      currentStructure.addPathNode(pathNode);
      visit(lowerBound);
      currentStructure.removePathNode(pathNode);
    }

    /**
     * Initialize {@code wildcard}'s super bound.
     *
     * @param wildcard wildcard whose super bound is initialized
     */
    public void initializeSuperBound(AnnotatedWildcardType wildcard) {
      AnnotatedTypeFactory typeFactory = wildcard.atypeFactory;

      WildcardType underlyingType = wildcard.getUnderlyingType();
      TypeMirror underlyingSuperBound = underlyingType.getSuperBound();
      if (underlyingSuperBound == null) {
        underlyingSuperBound =
            TypesUtils.wildLowerBound(underlyingType, wildcard.atypeFactory.processingEnv);
      }

      AnnotatedTypeMirror superBound =
          AnnotatedTypeMirror.createType(underlyingSuperBound, typeFactory, false);
      wildcard.setSuperBound(superBound);

      this.wildcards.put(wildcard.getUnderlyingType(), wildcard);

      TypePathNode superNode = currentStructure.addPathNode(new SuperBoundNode());
      visit(superBound);
      currentStructure.removePathNode(superNode);
    }

    /**
     * Initialize {@code wildcard}'s extends bound.
     *
     * @param wildcard wildcard whose extends bound is initialized
     */
    public void initializeExtendsBound(AnnotatedWildcardType wildcard) {
      AnnotatedTypeFactory typeFactory = wildcard.atypeFactory;

      WildcardType javaWildcardType = wildcard.getUnderlyingType();
      TypeMirror javaExtendsBound;
      if (javaWildcardType.getExtendsBound() != null) {
        // If the wildcard type has an extends bound, use it.
        javaExtendsBound = javaWildcardType.getExtendsBound();
      } else if (wildcard.getTypeVariable() != null) {
        // Otherwise use the upper bound of the type variable associated with this wildcard.
        javaExtendsBound = wildcard.getTypeVariable().getUpperBound();
      } else {
        // Otherwise use the upper bound of the java wildcard.
        javaExtendsBound =
            TypesUtils.wildUpperBound(javaWildcardType, wildcard.atypeFactory.processingEnv);
      }

      if (wildcard.isUninferredTypeArgument()) {
        rawTypeWildcards.put(wildcard.getTypeVariable(), wildcard.getUnderlyingType());
      }

      AnnotatedTypeMirror extendsBound =
          AnnotatedTypeMirror.createType(javaExtendsBound, typeFactory, false);
      wildcard.setExtendsBound(extendsBound);

      this.wildcards.put(wildcard.getUnderlyingType(), wildcard);

      TypePathNode extendsNode = currentStructure.addPathNode(new ExtendsBoundNode());
      visit(extendsBound);
      currentStructure.removePathNode(extendsNode);
    }

    /**
     * Initialize {@code declaredType}'s type arguments.
     *
     * @param declaredType declared type whose type arguments are initialized
     */
    private void initializeTypeArgs(AnnotatedDeclaredType declaredType) {
      DeclaredType underlyingType = (DeclaredType) declaredType.underlyingType;
      if (underlyingType.getTypeArguments().isEmpty() && !declaredType.wasRaw()) {
        return;
      }
      TypeElement typeElement =
          (TypeElement) declaredType.atypeFactory.types.asElement(underlyingType);
      List<AnnotatedTypeMirror> typeArgs;
      if (declaredType.typeArgs == null) {
        int numTypeParameters = typeElement.getTypeParameters().size();
        typeArgs = new ArrayList<>(numTypeParameters);
        for (int i = 0; i < numTypeParameters; i++) {
          TypeMirror javaTypeArg = getJavaType(declaredType, typeElement.getTypeParameters(), i);
          AnnotatedTypeMirror atmArg =
              AnnotatedTypeMirror.createType(javaTypeArg, declaredType.atypeFactory, false);
          typeArgs.add(atmArg);
          if (atmArg.getKind() == TypeKind.WILDCARD && declaredType.wasRaw()) {
            ((AnnotatedWildcardType) atmArg).setUninferredTypeArgument();
          }
        }
      } else {
        typeArgs = declaredType.typeArgs;
      }

      List<AnnotatedTypeMirror> typeArgReplacements = new ArrayList<>(typeArgs.size());
      for (int i = 0; i < typeArgs.size(); i++) {
        AnnotatedTypeMirror typeArg = typeArgs.get(i);
        TypePathNode node = currentStructure.addPathNode(new TypeArgNode(i));
        if (typeArg.getKind() == TypeKind.WILDCARD) {
          ((AnnotatedWildcardType) typeArg).setTypeVariable(typeElement.getTypeParameters().get(i));
        }
        typeArgReplacements.add(getOrVisit(typeArg));
        currentStructure.removePathNode(node);
      }

      declaredType.setTypeArguments(typeArgReplacements);
    }

    /**
     * Store the wildcards created as type arguments to raw types.
     *
     * <p>{@code class Foo<T extends Foo> {}} The upper bound of the wildcard in {@code Foo<?>} is
     * {@code Foo}. The type argument of {@code Foo} is initialized to {@code ? extends Foo}. The
     * type argument of {@code Foo} in {@code ? extends Foo} needs to be initialized to the same
     * type argument as the first {@code Foo} so that
     * BoundsInitializer.InitializerVisitor#getOrVisit will return the cached AnnotatedWildcardType.
     */
    private final Map<TypeVariable, WildcardType> rawTypeWildcards = new HashMap<>();

    /**
     * Returns the underlying java type of the {@code i}-th type argument of {@code type}. If {@code
     * type} is raw, then a new wildcard is created or returned from {@code rawTypeWildcards}.
     *
     * @param type declared type
     * @param parameters elements of the type parameters
     * @param i index of the type parameter
     * @return the underlying java type of the {@code i}-th type argument of {@code type}
     */
    private TypeMirror getJavaType(
        AnnotatedDeclaredType type, List<? extends TypeParameterElement> parameters, int i) {
      if (type.wasRaw()) {
        TypeVariable typeVariable = (TypeVariable) parameters.get(i).asType();
        if (rawTypeWildcards.containsKey(typeVariable)) {
          return rawTypeWildcards.get(typeVariable);
        }
        WildcardType wildcard = getUpperBoundAsWildcard(typeVariable, type.atypeFactory);
        rawTypeWildcards.put(typeVariable, wildcard);
        return wildcard;
      } else {
        return type.getUnderlyingType().getTypeArguments().get(i);
      }
    }

    /**
     * Replace all type variables in type with the AnnotatedTypeMirrors created when initializing
     * it.
     *
     * @param type all type variables are replaced
     */
    public void resolveTypeVarReferences(AnnotatedTypeMirror type) {
      List<AnnotatedTypeVariable> annotatedTypeVars = new ArrayList<>();
      if (type.getKind() == TypeKind.TYPEVAR) {
        annotatedTypeVars.add((AnnotatedTypeVariable) type);
      }

      // Gather a list of all AnnotatedTypeVariables and all the replacements to perform.
      for (TypeVariableStructure typeVarStruct : typeVarToStructure.values()) {
        typeVarStruct.findAllReplacements(typeVarToStructure);
        annotatedTypeVars.addAll(typeVarStruct.getAnnotatedTypeVars());
      }

      // Do the replacements.
      for (AnnotatedTypeVariable atv : annotatedTypeVars) {
        TypeVariableStructure list = typeVarToStructure.get(atv.getUnderlyingType());
        list.replaceTypeVariablesInType(atv);
      }

      if (type.getKind() == TypeKind.WILDCARD) {
        // Do the "top level" replacements.
        AnnotatedWildcardType wildcard = (AnnotatedWildcardType) type;
        topLevelStructure.findAllReplacements(typeVarToStructure);
        for (AnnotatedTypeVariable typeVar : topLevelStructure.getAnnotatedTypeVars()) {
          TypeVariableStructure list = typeVarToStructure.get(typeVar.getUnderlyingType());
          list.replaceTypeVariablesInType(typeVar);
        }
        topLevelStructure.replaceTypeVariablesInType(wildcard);
      }
    }
  }

  /**
   * Creates the upper bound type for {@code typeVar} and sets it.
   *
   * @param typeVar type variable
   * @return the newly created upper bound
   */
  private static AnnotatedTypeMirror createAndSetUpperBound(AnnotatedTypeVariable typeVar) {
    AnnotatedTypeMirror upperBound =
        AnnotatedTypeMirror.createType(
            typeVar.getUnderlyingType().getUpperBound(), typeVar.atypeFactory, false);
    typeVar.setUpperBound(upperBound);
    return upperBound;
  }

  /**
   * Creates the lower bound type for {@code typeVar} and sets it. If the type variable does not
   * have a lower bound, then a null type is created.
   *
   * @param typeVar type variable
   * @return the newly created lower bound
   */
  private static AnnotatedTypeMirror createAndSetLowerBound(AnnotatedTypeVariable typeVar) {
    TypeMirror lb = typeVar.getUnderlyingType().getLowerBound();
    if (lb == null) {
      // Use bottom type to ensure there is a lower bound.
      Context context =
          ((JavacProcessingEnvironment) typeVar.atypeFactory.processingEnv).getContext();
      Symtab syms = Symtab.instance(context);
      lb = syms.botType;
    }
    AnnotatedTypeMirror lowerBound =
        AnnotatedTypeMirror.createType(lb, typeVar.atypeFactory, false);
    typeVar.setLowerBound(lowerBound);
    return lowerBound;
  }

  /**
   * Contains all the type variables and the type path to reach them found when scanning a
   * particular type variable or wildcard. Then uses this information to replace the type variables
   * with AnnotatedTypeVariables.
   */
  private static class RecursiveTypeStructure {

    /** List of TypePath and TypeVariables that were found will traversing this type. */
    private final List<Pair<TypePath, TypeVariable>> typeVarsInType = new ArrayList<>();

    /** Current path used to mark the locations of TypeVariables. */
    private final TypePath currentPath = new TypePath();

    /**
     * Add a type variable found at the current path while visiting the type variable or wildcard
     * associated with this structure.
     *
     * @param typeVariable TypeVariable
     */
    public void addTypeVar(TypeVariable typeVariable) {
      typeVarsInType.add(Pair.of(this.currentPath.copy(), typeVariable));
    }

    /**
     * Add a node in the path.
     *
     * @param node node to add
     * @return {@code node}
     */
    public TypePathNode addPathNode(TypePathNode node) {
      currentPath.add(node);
      return node;
    }

    /**
     * Remove the last node in the path if it is {@code node}; otherwise, throw an exception.
     *
     * @param node last node in the path
     */
    public void removePathNode(@FindDistinct TypePathNode node) {
      if (currentPath.getLeaf() != node) {
        throw new BugInCF(
            "Cannot remove node: %s. It is not the last node. currentPath= %s", node, currentPath);
      }
      currentPath.removeLeaf();
    }

    /**
     * For all type variables contained within the type variable or wildcard that this structure
     * represents, this a list of the replacement {@link AnnotatedTypeVariable} for the location
     * specified by the {@link TypePath}.
     */
    private List<Pair<TypePath, AnnotatedTypeVariable>> replacementList;

    /**
     * Find the AnnotatedTypeVariables that should replace the type variables found in this type.
     *
     * @param typeVarToStructure a mapping from TypeVariable to TypeVariableStructure
     */
    public void findAllReplacements(Map<TypeVariable, TypeVariableStructure> typeVarToStructure) {
      this.annotatedTypeVariables = new ArrayList<>(typeVarsInType.size());
      this.replacementList = new ArrayList<>(typeVarsInType.size());
      for (Pair<TypePath, TypeVariable> pair : typeVarsInType) {
        TypeVariableStructure targetStructure = typeVarToStructure.get(pair.second);
        AnnotatedTypeVariable template = targetStructure.annotatedTypeVar.deepCopy().asUse();
        annotatedTypeVariables.add(template);
        replacementList.add(Pair.of(pair.first, template));
      }
    }

    /** List of {@link AnnotatedTypeVariable}s found in this type. */
    private List<AnnotatedTypeVariable> annotatedTypeVariables;

    /**
     * A list of all AnnotatedTypeVariables found in this type. {@link #findAllReplacements(Map)}
     * must be called first.
     *
     * @return a list of all AnnotatedTypeVariables found in this type
     */
    public List<AnnotatedTypeVariable> getAnnotatedTypeVars() {
      if (annotatedTypeVariables == null) {
        throw new BugInCF("Call createReplacementList before calling this method.");
      }
      return annotatedTypeVariables;
    }

    /**
     * Replaces all type variables in {@code type} with their replacements. ({@link
     * #findAllReplacements(Map)} must be called first so that the replacements can be found.)
     *
     * @param type annotated type whose type variables are replaced
     */
    public void replaceTypeVariablesInType(AnnotatedTypeMirror type) {
      if (replacementList == null) {
        throw new BugInCF("Call createReplacementList before calling this method.");
      }
      for (Pair<TypePath, AnnotatedTypeVariable> entry : replacementList) {
        TypePath path = entry.first;
        AnnotatedTypeVariable replacement = entry.second;
        path.replaceTypeVariable(type, replacement);
      }
    }
  }

  /** A {@link RecursiveTypeStructure} for a type variable. */
  private static class TypeVariableStructure extends RecursiveTypeStructure {
    /** The type variable whose structure is being described. */
    public final TypeVariable typeVar;

    /**
     * The first annotated type variable that was encountered and traversed in order to describe
     * typeVar. It is expanded during visitation and it is later used as a template for other uses
     * of typeVar
     */
    public final AnnotatedTypeVariable annotatedTypeVar;

    /**
     * Creates an {@link TypeVariableStructure}
     *
     * @param annotatedTypeVar annotated type for the type variable whose structure is being
     *     described
     */
    public TypeVariableStructure(AnnotatedTypeVariable annotatedTypeVar) {
      this.typeVar = annotatedTypeVar.getUnderlyingType();
      this.annotatedTypeVar = annotatedTypeVar;
    }
  }

  /**
   * A list of {@link TypePathNode}s. Each node represents a "location" of a composite type. For
   * example, an {@link UpperBoundNode} represents the upper bound type of a type variable
   */
  @SuppressWarnings("serial")
  private static class TypePath extends ArrayList<TypePathNode> {

    @Override
    public String toString() {
      return StringsPlume.join(",", this);
    }

    /**
     * Create a copy of this path.
     *
     * @return a copy of this path
     */
    public TypePath copy() {
      TypePath copy = new TypePath();
      for (TypePathNode node : this) {
        copy.add(node.copy());
      }
      return copy;
    }

    /**
     * Return the leaf node of this path.
     *
     * @return the leaf node or null if the path is empty
     */
    public TypePathNode getLeaf() {
      if (this.isEmpty()) {
        return null;
      }
      return this.get(size() - 1);
    }

    /** Remove the leaf node if one exists. */
    public void removeLeaf() {
      if (this.isEmpty()) {
        return;
      }
      this.remove(size() - 1);
    }

    /**
     * In {@code type}, replace the type at the location specified by this path with {@code
     * replacement}.
     *
     * @param type annotated type that is side-effected
     * @param replacement annotated type to add to {@code type}
     */
    public void replaceTypeVariable(AnnotatedTypeMirror type, AnnotatedTypeVariable replacement) {
      AnnotatedTypeMirror current = type;
      for (int i = 0; i < size() - 1; i++) {
        current = get(i).getType(current);
      }
      this.getLeaf().replaceType(current, replacement);
    }
  }

  /**
   * A {@link TypePathNode} represents a "location" of a composite type. For example, an {@link
   * UpperBoundNode} represents the upper bound type of a type variable.
   */
  private abstract static class TypePathNode {

    /** The {@link TypeKind} of the parent of this node. */
    public final TypeKind parentTypeKind;

    /**
     * Creates a {@link TypePathNode}.
     *
     * @param parentTypeKind kind of parent of this node
     */
    TypePathNode(TypeKind parentTypeKind) {
      this.parentTypeKind = parentTypeKind;
    }

    /**
     * A copy constructor.
     *
     * @param template node to copy
     */
    TypePathNode(TypePathNode template) {
      this.parentTypeKind = template.parentTypeKind;
    }

    @Override
    public String toString() {
      return this.getClass().getSimpleName();
    }

    /**
     * Returns the annotated type at the location represented by this node in {@code type}.
     *
     * @param type parent type
     * @return the annotated type at the location represented by this node in {@code type}
     * @throws BugInCF if {@code type} does not have a type at this location
     */
    public final AnnotatedTypeMirror getType(AnnotatedTypeMirror type) {
      abortIfNotKind(parentTypeKind, null, type);
      return getTypeInternal(type);
    }

    /**
     * Internal implementation of {@link #getType(AnnotatedTypeMirror)}.
     *
     * @param parent type that is sideffected by this method
     * @return the annotated type at the location represented by this node in {@code type}
     */
    protected abstract AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent);

    /**
     * Replaces the type at the location represented by this node in {@code parent} with {@code
     * replacement}.
     *
     * @param parent type that is sideffected by this method
     * @param replacement the replacement
     * @throws BugInCF if {@code type} does not have a type at this location
     */
    public final void replaceType(AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      abortIfNotKind(parentTypeKind, replacement, parent);
      replaceTypeInternal(parent, replacement);
    }

    /**
     * Internal implementation of #replaceType.
     *
     * @param parent type that is sideffected by this method
     * @param replacement the replacement
     */
    protected abstract void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement);

    /**
     * Returns a copy of the node.
     *
     * @return a copy of this node
     */
    public abstract TypePathNode copy();

    /**
     * Throws a {@link BugInCF} if {@code parent} is {@code typeKind}.
     *
     * @param typeKind TypeKind
     * @param replacement for debugging
     * @param parent possible parent type of this node
     * @throws BugInCF if {@code parent} is {@code typeKind}
     */
    private void abortIfNotKind(
        TypeKind typeKind, AnnotatedTypeVariable replacement, AnnotatedTypeMirror parent) {
      if (parent.getKind() == typeKind) {
        return;
      }

      throw new BugInCF(
          "Unexpected parent kind:%nparent= %s%nreplacements= %s%n expected= %s",
          parent, replacement, typeKind);
    }
  }

  /** Represents an enclosing type of a declared type. */
  private static class EnclosingTypeNode extends TypePathNode {

    /** Create an enclosing node. */
    EnclosingTypeNode() {
      super(TypeKind.DECLARED);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      // An enclosing type cannot be a type variable, so do nothing.
    }

    @Override
    public AnnotatedDeclaredType getTypeInternal(AnnotatedTypeMirror parent) {
      return ((AnnotatedDeclaredType) parent).getEnclosingType();
    }

    @Override
    public TypePathNode copy() {
      return new EnclosingTypeNode();
    }
  }

  /** Represents an extends bound of a wildcard. */
  private static class ExtendsBoundNode extends TypePathNode {
    /** Creates an ExtendsBoundNode. */
    ExtendsBoundNode() {
      super(TypeKind.WILDCARD);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      ((AnnotatedWildcardType) parent).setExtendsBound(replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      return ((AnnotatedWildcardType) parent).getExtendsBound();
    }

    @Override
    public TypePathNode copy() {
      return new ExtendsBoundNode();
    }
  }

  /** Represents a super bound of a wildcard. */
  private static class SuperBoundNode extends TypePathNode {
    /** Creates a SuperBoundNode. */
    SuperBoundNode() {
      super(TypeKind.WILDCARD);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      ((AnnotatedWildcardType) parent).setSuperBound(replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      return ((AnnotatedWildcardType) parent).getSuperBound();
    }

    @Override
    public TypePathNode copy() {
      return new SuperBoundNode();
    }
  }

  /** Represents an upper bound of a type variable. */
  private static class UpperBoundNode extends TypePathNode {

    /** Creates an UpperBoundNode. */
    UpperBoundNode() {
      super(TypeKind.TYPEVAR);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      ((AnnotatedTypeVariable) parent).setUpperBound(replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      AnnotatedTypeVariable parentAtv = (AnnotatedTypeVariable) parent;
      if (parentAtv.getUpperBoundField() != null) {
        return parentAtv.getUpperBoundField();
      }
      return createAndSetUpperBound((AnnotatedTypeVariable) parent);
    }

    @Override
    public TypePathNode copy() {
      return new UpperBoundNode();
    }
  }

  /** Represents a lower bound of a type variable. */
  private static class LowerBoundNode extends TypePathNode {

    /** Creates a LowerBoundNode. */
    LowerBoundNode() {
      super(TypeKind.TYPEVAR);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      ((AnnotatedTypeVariable) parent).setLowerBound(replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {

      AnnotatedTypeVariable parentAtv = (AnnotatedTypeVariable) parent;
      if (parentAtv.getLowerBoundField() != null) {
        return parentAtv.getLowerBoundField();
      }
      // else // TODO: I think this should never happen at this point, throw exception
      return createAndSetLowerBound((AnnotatedTypeVariable) parent);
    }

    @Override
    public TypePathNode copy() {
      return new LowerBoundNode();
    }
  }

  /** Represents a component type of an array type. */
  private static class ArrayComponentNode extends TypePathNode {

    /** Create ArrayComponentNode. */
    ArrayComponentNode() {
      super(TypeKind.ARRAY);
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      ((AnnotatedArrayType) parent).setComponentType(replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      return ((AnnotatedArrayType) parent).getComponentType();
    }

    @Override
    public TypePathNode copy() {
      return new ArrayComponentNode();
    }
  }

  /** A bound type of an intersection type. */
  private static class IntersectionBoundNode extends TypePathNode {

    /** The index of the particular bound type of an intersection type this node represents. */
    public final int boundIndex;

    /**
     * Creates an IntersectionBoundNode.
     *
     * @param boundIndex the index of the particular bound type of an intersection type this node
     *     represents
     */
    IntersectionBoundNode(int boundIndex) {
      super(TypeKind.INTERSECTION);
      this.boundIndex = boundIndex;
    }

    /**
     * Copy constructor.
     *
     * @param template node to copy
     */
    IntersectionBoundNode(IntersectionBoundNode template) {
      super(template);
      boundIndex = template.boundIndex;
    }

    @Override
    public String toString() {
      return super.toString() + "( superIndex=" + boundIndex + " )";
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      AnnotatedIntersectionType intersection = (AnnotatedIntersectionType) parent;
      List<AnnotatedTypeMirror> bounds = new ArrayList<>(intersection.bounds);
      bounds.set(boundIndex, replacement);
      intersection.setBounds(bounds);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      AnnotatedIntersectionType isect = (AnnotatedIntersectionType) parent;
      if (isect.getBounds().size() <= boundIndex) {
        throw new BugInCF("Invalid superIndex %d: parent=%s", boundIndex, parent);
      }

      return isect.getBounds().get(boundIndex);
    }

    @Override
    public TypePathNode copy() {
      return new IntersectionBoundNode(this);
    }
  }

  /** Represents an alternative type of a union node. */
  private static class AlternativeTypeNode extends TypePathNode {

    /** The index of the particular alternative type of the union node that this node represents. */
    public final int altIndex;

    /**
     * Creates a AlternativeTypeNode.
     *
     * @param altIndex the index of the particular alternative type of the union node that this node
     *     represents
     */
    AlternativeTypeNode(int altIndex) {
      super(TypeKind.UNION);
      this.altIndex = altIndex;
    }

    /**
     * Copy constructor.
     *
     * @param template node to copy
     */
    AlternativeTypeNode(AlternativeTypeNode template) {
      super(template);
      altIndex = template.altIndex;
    }

    @Override
    public String toString() {
      return super.toString() + "( altIndex=" + altIndex + " )";
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      throw new BugInCF(
          "Union types cannot be intersection bounds.%nparent=%s%nreplacement=%s",
          parent, replacement);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      AnnotatedUnionType isect = (AnnotatedUnionType) parent;
      if (parent.directSupertypes().size() <= altIndex) {
        throw new BugInCF("Invalid altIndex( %s ):%nparent=%s", altIndex, parent);
      }

      return isect.directSupertypes().get(altIndex);
    }

    @Override
    public TypePathNode copy() {
      return new AlternativeTypeNode(this);
    }
  }

  /** Represents a type argument of a declared type. */
  private static class TypeArgNode extends TypePathNode {

    /** The index of the type argument that this node represents. */
    public final int argIndex;

    /**
     * Creates a TypeArgumentNode.
     *
     * @param argIndex index of the type argument that this node represents
     */
    TypeArgNode(int argIndex) {
      super(TypeKind.DECLARED);
      this.argIndex = argIndex;
    }

    /**
     * Copy constructor.
     *
     * @param template node to copy
     */
    TypeArgNode(TypeArgNode template) {
      super(template);
      this.argIndex = template.argIndex;
    }

    @Override
    public String toString() {
      return super.toString() + "( argIndex=" + argIndex + " )";
    }

    @Override
    protected void replaceTypeInternal(
        AnnotatedTypeMirror parent, AnnotatedTypeVariable replacement) {
      AnnotatedDeclaredType parentAdt = (AnnotatedDeclaredType) parent;
      List<AnnotatedTypeMirror> typeArgs = new ArrayList<>(parentAdt.getTypeArguments());
      if (argIndex >= typeArgs.size()) {
        throw new BugInCF(
            StringsPlume.joinLines(
                "Invalid type arg index.",
                "parent=" + parent,
                "replacement=" + replacement,
                "argIndex=" + argIndex));
      }
      typeArgs.add(argIndex, replacement);
      typeArgs.remove(argIndex + 1);
      parentAdt.setTypeArguments(typeArgs);
    }

    @Override
    protected AnnotatedTypeMirror getTypeInternal(AnnotatedTypeMirror parent) {
      AnnotatedDeclaredType parentAdt = (AnnotatedDeclaredType) parent;

      List<AnnotatedTypeMirror> typeArgs = parentAdt.getTypeArguments();
      if (argIndex >= typeArgs.size()) {
        throw new BugInCF(
            StringsPlume.joinLines(
                "Invalid type arg index.", "parent=" + parent, "argIndex=" + argIndex));
      }

      return typeArgs.get(argIndex);
    }

    @Override
    public TypePathNode copy() {
      return new TypeArgNode(this);
    }
  }
}
