package org.checkerframework.framework.util;

import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.WildcardType;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
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.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.AsSuperVisitor;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.SyntheticArrays;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.CollectionsPlume;
import org.plumelib.util.StringsPlume;

/**
 * Utility methods for operating on {@code AnnotatedTypeMirror}. This class mimics the class {@link
 * Types}.
 */
public class AnnotatedTypes {
  /** Class cannot be instantiated. */
  private AnnotatedTypes() {
    throw new AssertionError("Class AnnotatedTypes cannot be instantiated.");
  }

  private static AsSuperVisitor asSuperVisitor;

  /**
   * Copies annotations from {@code type} to a copy of {@code superType} where the type variables of
   * {@code superType} have been substituted. How the annotations are copied depends on the kinds of
   * AnnotatedTypeMirrors given. Generally, if {@code type} and {@code superType} are both declared
   * types, asSuper is called recursively on the direct super types, see {@link
   * AnnotatedTypeMirror#directSupertypes()}, of {@code type} until {@code type}'s erased Java type
   * is the same as {@code superType}'s erased super type. Then {@code type is returned}. For
   * compound types, asSuper is called recursively on components.
   *
   * <p>Preconditions:<br>
   * {@code superType} may have annotations, but they are ignored. <br>
   * {@code type} may not be an instanceof AnnotatedNullType, because if {@code superType} is a
   * compound type, the annotations on the component types are undefined.<br>
   * The underlying {@code type} (ie the Java type) of {@code type} should be a subtype (or the same
   * type) of the underlying type of {@code superType}. Except for these cases:
   *
   * <ul>
   *   <li>If {@code type} is a primitive, then the boxed type of {@code type} must be subtype of
   *       {@code superType}.
   *   <li>If {@code superType} is a primitive, then {@code type} must be convertible to {@code
   *       superType}.
   *   <li>If {@code superType} is a type variable or wildcard without a lower bound, then {@code
   *       type} must be a subtype of the upper bound of {@code superType}. (This relaxed rule is
   *       used during type argument inference where the type variable or wildcard is the type
   *       argument that was inferred.)
   *   <li>If {@code superType} is a wildcard with a lower bound, then {@code type} must be a
   *       subtype of the lower bound of {@code superType}.
   * </ul>
   *
   * <p>Postconditions: {@code type} and {@code superType} are not modified.
   *
   * @param atypeFactory {@link AnnotatedTypeFactory}
   * @param type type from which to copy annotations
   * @param superType a type whose erased Java type is a supertype of {@code type}'s erased Java
   *     type.
   * @return {@code superType} with annotations copied from {@code type} and type variables
   *     substituted from {@code type}.
   */
  public static <T extends AnnotatedTypeMirror> T asSuper(
      AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror type, T superType) {
    if (asSuperVisitor == null || !asSuperVisitor.sameAnnotatedTypeFactory(atypeFactory)) {
      asSuperVisitor = new AsSuperVisitor(atypeFactory);
    }
    return asSuperVisitor.asSuper(type, superType);
  }

  /**
   * Calls asSuper and casts the result to the same type as the input supertype.
   *
   * @param subtype subtype to be transformed to supertype
   * @param supertype supertype that subtype is transformed to
   * @param <T> the type of supertype and return type
   * @return subtype as an instance of supertype
   */
  public static <T extends AnnotatedTypeMirror> T castedAsSuper(
      final AnnotatedTypeFactory atypeFactory,
      final AnnotatedTypeMirror subtype,
      final T supertype) {
    final Types types = atypeFactory.getProcessingEnv().getTypeUtils();
    final Elements elements = atypeFactory.getProcessingEnv().getElementUtils();

    if (subtype.getKind() == TypeKind.NULL) {
      // Make a copy of the supertype so that if supertype is a composite type, the
      // returned type will be fully annotated.  (For example, if sub is @C null and super is
      // @A List<@B String>, then the returned type is @C List<@B String>.)
      @SuppressWarnings("unchecked")
      T copy = (T) supertype.deepCopy();
      copy.replaceAnnotations(subtype.getAnnotations());
      return copy;
    }

    final T asSuperType = AnnotatedTypes.asSuper(atypeFactory, subtype, supertype);

    fixUpRawTypes(subtype, asSuperType, supertype, types);

    // if we have a type for enum MyEnum {...}
    // When the supertype is the declaration of java.lang.Enum<E>, MyEnum values become
    // Enum<MyEnum>.  Where really, we would like an Enum<E> with the annotations from
    // Enum<MyEnum> are transferred to Enum<E>.  That is, if we have a type:
    // @1 Enum<@2 MyEnum>
    // asSuper should return:
    // @1 Enum<E extends @2 Enum<E>>
    if (asSuperType != null
        && AnnotatedTypes.isEnum(asSuperType)
        && AnnotatedTypes.isDeclarationOfJavaLangEnum(types, elements, supertype)) {
      final AnnotatedDeclaredType resultAtd = ((AnnotatedDeclaredType) supertype).deepCopy();
      resultAtd.clearAnnotations();
      resultAtd.addAnnotations(asSuperType.getAnnotations());

      final AnnotatedDeclaredType asSuperAdt = (AnnotatedDeclaredType) asSuperType;
      if (!resultAtd.getTypeArguments().isEmpty() && !asSuperAdt.getTypeArguments().isEmpty()) {
        final AnnotatedTypeMirror sourceTypeArg = asSuperAdt.getTypeArguments().get(0);
        final AnnotatedTypeMirror resultTypeArg = resultAtd.getTypeArguments().get(0);
        resultTypeArg.clearAnnotations();
        if (resultTypeArg.getKind() == TypeKind.TYPEVAR) {
          // Only change the upper bound of a type variable.
          AnnotatedTypeVariable resultTypeArgTV = (AnnotatedTypeVariable) resultTypeArg;
          resultTypeArgTV.getUpperBound().addAnnotations(sourceTypeArg.getAnnotations());
        } else {
          resultTypeArg.addAnnotations(sourceTypeArg.getEffectiveAnnotations());
        }
        @SuppressWarnings("unchecked")
        T result = (T) resultAtd;
        return result;
      }
    }
    return asSuperType;
  }

  /**
   * Some times we create type arguments for types that were raw. When we do an asSuper we lose
   * these arguments. If in the converted type (i.e. the subtype as super) is missing type arguments
   * AND those type arguments should come from the original subtype's type arguments then we copy
   * the original type arguments to the converted type. e.g. We have a type W, that "wasRaw" {@code
   * ArrayList<? extends Object>} When W is converted to type A, List, using asSuper it no longer
   * has its type argument. But since the type argument to List should be the same as that to
   * ArrayList we copy over the type argument of W to A. A becomes {@code List<? extends Object>}
   *
   * @param originalSubtype the subtype before being converted by asSuper
   * @param asSuperType he subtype after being converted by asSuper
   * @param supertype the supertype for which asSuperType should have the same underlying type
   * @param types the types utility
   */
  private static void fixUpRawTypes(
      final AnnotatedTypeMirror originalSubtype,
      final AnnotatedTypeMirror asSuperType,
      final AnnotatedTypeMirror supertype,
      final Types types) {
    if (asSuperType == null
        || asSuperType.getKind() != TypeKind.DECLARED
        || originalSubtype.getKind() != TypeKind.DECLARED) {
      return;
    }

    final AnnotatedDeclaredType declaredAsSuper = (AnnotatedDeclaredType) asSuperType;
    final AnnotatedDeclaredType declaredSubtype = (AnnotatedDeclaredType) originalSubtype;

    if (!declaredAsSuper.wasRaw()
        || !declaredAsSuper.getTypeArguments().isEmpty()
        || declaredSubtype.getTypeArguments().isEmpty()) {
      return;
    }

    Set<Pair<Integer, Integer>> typeArgMap =
        TypeArgumentMapper.mapTypeArgumentIndices(
            (TypeElement) declaredSubtype.getUnderlyingType().asElement(),
            (TypeElement) declaredAsSuper.getUnderlyingType().asElement(),
            types);

    if (typeArgMap.size() != declaredSubtype.getTypeArguments().size()) {
      return;
    }

    List<Pair<Integer, Integer>> orderedByDestination = new ArrayList<>(typeArgMap);
    orderedByDestination.sort(Comparator.comparingInt(o -> o.second));

    if (typeArgMap.size() == ((AnnotatedDeclaredType) supertype).getTypeArguments().size()) {
      List<? extends AnnotatedTypeMirror> subTypeArgs = declaredSubtype.getTypeArguments();
      List<AnnotatedTypeMirror> newTypeArgs =
          CollectionsPlume.mapList(
              mapping -> subTypeArgs.get(mapping.first).deepCopy(), orderedByDestination);
      declaredAsSuper.setTypeArguments(newTypeArgs);
    } else {
      declaredAsSuper.setTypeArguments(Collections.emptyList());
    }
  }

  /** This method identifies wildcard types that are unbound. */
  public static boolean hasNoExplicitBound(final AnnotatedTypeMirror wildcard) {
    return ((Type.WildcardType) wildcard.getUnderlyingType()).isUnbound();
  }

  /**
   * This method identifies wildcard types that have an explicit super bound. NOTE:
   * Type.WildcardType.isSuperBound will return true for BOTH unbound and super bound wildcards
   * which necessitates this method
   */
  public static boolean hasExplicitSuperBound(final AnnotatedTypeMirror wildcard) {
    final Type.WildcardType wildcardType = (Type.WildcardType) wildcard.getUnderlyingType();
    return wildcardType.isSuperBound()
        && !((WildcardType) wildcard.getUnderlyingType()).isUnbound();
  }

  /**
   * This method identifies wildcard types that have an explicit extends bound. NOTE:
   * Type.WildcardType.isExtendsBound will return true for BOTH unbound and extends bound wildcards
   * which necessitates this method
   */
  public static boolean hasExplicitExtendsBound(final AnnotatedTypeMirror wildcard) {
    final Type.WildcardType wildcardType = (Type.WildcardType) wildcard.getUnderlyingType();
    return wildcardType.isExtendsBound()
        && !((WildcardType) wildcard.getUnderlyingType()).isUnbound();
  }

  /**
   * Return the base type of type or any of its outer types that starts with the given type. If none
   * exists, return null.
   *
   * @param type a type
   * @param superType a type
   */
  private static AnnotatedTypeMirror asOuterSuper(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror type,
      AnnotatedTypeMirror superType) {
    if (type.getKind() == TypeKind.DECLARED) {
      AnnotatedDeclaredType dt = (AnnotatedDeclaredType) type;
      AnnotatedDeclaredType enclosingType = dt;
      TypeMirror superTypeMirror = types.erasure(superType.getUnderlyingType());
      while (enclosingType != null) {
        TypeMirror enclosingTypeMirror = types.erasure(enclosingType.getUnderlyingType());
        if (types.isSubtype(enclosingTypeMirror, superTypeMirror)) {
          dt = enclosingType;
          break;
        }
        enclosingType = enclosingType.getEnclosingType();
      }
      if (enclosingType == null) {
        // TODO: https://github.com/typetools/checker-framework/issues/724
        // testcase javacheck -processor nullness  src/java/util/AbstractMap.java
        //                SourceChecker checker =  atypeFactory.getChecker().getChecker();
        //                String msg = (String.format("OuterAsSuper did not find outer
        // class. type: %s superType: %s", type, superType));
        //                checker.message(Kind.WARNING, msg);
        return superType;
      }
      return asSuper(atypeFactory, dt, superType);
    }
    return asSuper(atypeFactory, type, superType);
  }

  /**
   * Specialization of {@link #asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror,
   * Element)} with more precise return type.
   *
   * @see #asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element)
   * @param types the Types instance to use
   * @param atypeFactory the type factory to use
   * @param t the receiver type
   * @param elem the element that should be viewed as member of t
   * @return the type of elem as member of t
   */
  public static AnnotatedExecutableType asMemberOf(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror t,
      ExecutableElement elem) {
    return (AnnotatedExecutableType) asMemberOf(types, atypeFactory, t, (Element) elem);
  }

  /**
   * Specialization of {@link #asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element,
   * AnnotatedTypeMirror)} with more precise return type.
   *
   * @see #asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element,
   *     AnnotatedTypeMirror)
   * @param types the Types instance to use
   * @param atypeFactory the type factory to use
   * @param t the receiver type
   * @param elem the element that should be viewed as member of t
   * @param type unsubstituted type of member
   * @return the type of member as member of of, with initial type memberType; can be an alias to
   *     memberType
   */
  public static AnnotatedExecutableType asMemberOf(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror t,
      ExecutableElement elem,
      AnnotatedExecutableType type) {
    return (AnnotatedExecutableType) asMemberOf(types, atypeFactory, t, (Element) elem, type);
  }

  /**
   * Returns the type of an element when that element is viewed as a member of, or otherwise
   * directly contained by, a given type.
   *
   * <p>For example, when viewed as a member of the parameterized type {@code Set<@NonNull String>},
   * the {@code Set.add} method is an {@code ExecutableType} whose parameter is of type
   * {@code @NonNull String}.
   *
   * <p>Before returning the result, this method adjusts it by calling {@link
   * AnnotatedTypeFactory#postAsMemberOf(AnnotatedTypeMirror, AnnotatedTypeMirror, Element)}.
   *
   * <p>Note that this method does not currently return (top level) captured types for type
   * parameters, parameters, and return types. Instead, the original wildcard is returned, or
   * sometimes inferring type arguments will create a wildcard type which is returned. The bounds of
   * an inferred wildcard may itself have captures.
   *
   * <p>To prevent unsoundness, the rest of the Checker Framework must handle wildcards in places
   * where captures should appear (like type arguments). This should just involve the bounds of the
   * wildcard where the bounds of the capture would have been used.
   *
   * @param types the Types instance to use
   * @param atypeFactory the type factory to use
   * @param t the receiver type
   * @param elem the element that should be viewed as member of t
   * @return the type of elem as member of t
   */
  public static AnnotatedTypeMirror asMemberOf(
      Types types, AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror t, Element elem) {
    final AnnotatedTypeMirror memberType = atypeFactory.getAnnotatedType(elem);
    return asMemberOf(types, atypeFactory, t, elem, memberType);
  }

  /**
   * Returns the type of an element when that element is viewed as a member of, or otherwise
   * directly contained by, a given type. An initial type for the member is provided, to allow for
   * earlier changes to the declared type of elem. For example, polymorphic qualifiers must be
   * substituted before type variables are substituted.
   *
   * @param types the Types instance to use
   * @param atypeFactory the type factory to use
   * @param t the receiver type
   * @param elem the element that should be viewed as member of t
   * @param elemType unsubstituted type of elem
   * @return the type of elem as member of t
   * @see #asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror, Element)
   */
  public static AnnotatedTypeMirror asMemberOf(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      @Nullable AnnotatedTypeMirror t,
      Element elem,
      AnnotatedTypeMirror elemType) {
    // asMemberOf is only for fields, variables, and methods!
    // Otherwise, simply use fromElement.
    switch (elem.getKind()) {
      case PACKAGE:
      case INSTANCE_INIT:
      case OTHER:
      case STATIC_INIT:
      case TYPE_PARAMETER:
        return elemType;
      default:
        if (t == null || ElementUtils.isStatic(elem)) {
          return elemType;
        }
        AnnotatedTypeMirror res = asMemberOfImpl(types, atypeFactory, t, elem, elemType);
        atypeFactory.postAsMemberOf(res, t, elem);
        return res;
    }
  }

  /**
   * Helper for {@link AnnotatedTypes#asMemberOf(Types, AnnotatedTypeFactory, AnnotatedTypeMirror,
   * Element)}.
   *
   * @param types the Types instance to use
   * @param atypeFactory the type factory to use
   * @param receiverType the receiver type
   * @param member the element that should be viewed as member of receiverType
   * @param memberType unsubstituted type of member
   * @return the type of member as a member of receiverType; can be an alias to memberType
   */
  private static AnnotatedTypeMirror asMemberOfImpl(
      final Types types,
      final AnnotatedTypeFactory atypeFactory,
      final AnnotatedTypeMirror receiverType,
      final Element member,
      final AnnotatedTypeMirror memberType) {
    switch (receiverType.getKind()) {
      case ARRAY:
        // Method references like String[]::clone should have a return type of String[]
        // rather than Object.
        if (SyntheticArrays.isArrayClone(receiverType, member)) {
          return SyntheticArrays.replaceReturnType(member, (AnnotatedArrayType) receiverType);
        }
        return memberType;
      case TYPEVAR:
        return asMemberOf(
            types,
            atypeFactory,
            ((AnnotatedTypeVariable) receiverType).getUpperBound(),
            member,
            memberType);
      case WILDCARD:
        if (((AnnotatedWildcardType) receiverType).isUninferredTypeArgument()) {
          return substituteUninferredTypeArgs(atypeFactory, member, memberType);
        }
        return asMemberOf(
            types,
            atypeFactory,
            ((AnnotatedWildcardType) receiverType).getExtendsBound().deepCopy(),
            member,
            memberType);
      case INTERSECTION:
        AnnotatedTypeMirror result = memberType;
        for (AnnotatedTypeMirror bound : ((AnnotatedIntersectionType) receiverType).getBounds()) {
          result = substituteTypeVariables(types, atypeFactory, bound, member, result);
        }
        return result;
      case UNION:
      case DECLARED:
        return substituteTypeVariables(types, atypeFactory, receiverType, member, memberType);
      default:
        throw new BugInCF("asMemberOf called on unexpected type.%nt: %s", receiverType);
    }
  }

  /**
   * Substitute type variables.
   *
   * @param types type utilities
   * @param atypeFactory the type factory
   * @param receiverType the type of the class that contains member (or a subtype of it)
   * @param member a type member, such as a method or field
   * @param memberType the type of {@code member}
   * @return {@code memberType}, substituted
   */
  private static AnnotatedTypeMirror substituteTypeVariables(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror receiverType,
      Element member,
      AnnotatedTypeMirror memberType) {

    // Basic Algorithm:
    // 1. Find the enclosingClassOfMember of the element
    // 2. Find the base type of enclosingClassOfMember (e.g. type of enclosingClassOfMember as
    //      supertype of passed type)
    // 3. Substitute for type variables if any exist
    TypeElement enclosingClassOfMember = ElementUtils.enclosingTypeElement(member);
    final Map<TypeVariable, AnnotatedTypeMirror> mappings = new HashMap<>();

    // Look for all enclosing classes that have type variables
    // and collect type to be substituted for those type variables
    while (enclosingClassOfMember != null) {
      addTypeVarMappings(types, atypeFactory, receiverType, enclosingClassOfMember, mappings);
      enclosingClassOfMember =
          ElementUtils.enclosingTypeElement(enclosingClassOfMember.getEnclosingElement());
    }

    if (!mappings.isEmpty()) {
      memberType = atypeFactory.getTypeVarSubstitutor().substitute(mappings, memberType);
    }

    return memberType;
  }

  private static void addTypeVarMappings(
      Types types,
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror t,
      TypeElement enclosingClassOfElem,
      Map<TypeVariable, AnnotatedTypeMirror> mappings) {
    if (enclosingClassOfElem.getTypeParameters().isEmpty()) {
      return;
    }
    AnnotatedDeclaredType enclosingType = atypeFactory.getAnnotatedType(enclosingClassOfElem);
    AnnotatedDeclaredType base =
        (AnnotatedDeclaredType) asOuterSuper(types, atypeFactory, t, enclosingType);

    final List<AnnotatedTypeVariable> ownerParams =
        new ArrayList<>(enclosingType.getTypeArguments().size());
    for (final AnnotatedTypeMirror typeParam : enclosingType.getTypeArguments()) {
      if (typeParam.getKind() != TypeKind.TYPEVAR) {
        throw new BugInCF(
            StringsPlume.joinLines(
                "Type arguments of a declaration should be type variables.",
                "  enclosingClassOfElem=" + enclosingClassOfElem,
                "  enclosingType=" + enclosingType,
                "  typeMirror=" + t));
      }
      ownerParams.add((AnnotatedTypeVariable) typeParam);
    }

    List<AnnotatedTypeMirror> baseParams = base.getTypeArguments();
    if (ownerParams.size() != baseParams.size() && !base.wasRaw()) {
      throw new BugInCF(
          StringsPlume.joinLines(
              "Unexpected number of parameters.",
              "enclosingType=" + enclosingType,
              "baseType=" + base));
    }
    if (!ownerParams.isEmpty() && baseParams.isEmpty() && base.wasRaw()) {
      // If base type was raw and the type arguments are missing, set them to the erased
      // type of the type variable (which is the erased type of the upper bound).
      baseParams = CollectionsPlume.mapList(AnnotatedTypeVariable::getErased, ownerParams);
    }

    for (int i = 0; i < ownerParams.size(); ++i) {
      mappings.put(ownerParams.get(i).getUnderlyingType(), baseParams.get(i));
    }
  }

  /**
   * Substitutes uninferred type arguments for type variables in {@code memberType}.
   *
   * @param atypeFactory the type factory
   * @param member the element with type {@code memberType}; used to obtain the enclosing type
   * @param memberType the type to side-effect
   * @return memberType, with type arguments substituted for type variables
   */
  private static AnnotatedTypeMirror substituteUninferredTypeArgs(
      AnnotatedTypeFactory atypeFactory, Element member, AnnotatedTypeMirror memberType) {
    TypeElement enclosingClassOfMember = ElementUtils.enclosingTypeElement(member);
    final Map<TypeVariable, AnnotatedTypeMirror> mappings = new HashMap<>();

    while (enclosingClassOfMember != null) {
      if (!enclosingClassOfMember.getTypeParameters().isEmpty()) {
        AnnotatedDeclaredType enclosingType = atypeFactory.getAnnotatedType(enclosingClassOfMember);
        for (final AnnotatedTypeMirror type : enclosingType.getTypeArguments()) {
          AnnotatedTypeVariable typeParameter = (AnnotatedTypeVariable) type;
          mappings.put(
              typeParameter.getUnderlyingType(),
              atypeFactory.getUninferredWildcardType(typeParameter));
        }
      }
      enclosingClassOfMember =
          ElementUtils.enclosingTypeElement(enclosingClassOfMember.getEnclosingElement());
    }

    if (!mappings.isEmpty()) {
      return atypeFactory.getTypeVarSubstitutor().substitute(mappings, memberType);
    }

    return memberType;
  }

  /**
   * Returns all the supertypes (direct or indirect) of the given declared type.
   *
   * @param type a declared type
   * @return all the supertypes of the given type
   */
  public static Set<AnnotatedDeclaredType> getSuperTypes(AnnotatedDeclaredType type) {

    Set<AnnotatedDeclaredType> supertypes = new LinkedHashSet<>();
    if (type == null) {
      return supertypes;
    }

    // Set up a stack containing the type mirror of subtype, which
    // is our starting point.
    Deque<AnnotatedDeclaredType> stack = new ArrayDeque<>();
    stack.push(type);

    while (!stack.isEmpty()) {
      AnnotatedDeclaredType current = stack.pop();

      // For each direct supertype of the current type, if it
      // hasn't already been visited, push it onto the stack and
      // add it to our supertypes set.
      for (AnnotatedDeclaredType supertype : current.directSupertypes()) {
        if (!supertypes.contains(supertype)) {
          stack.push(supertype);
          supertypes.add(supertype);
        }
      }
    }

    return Collections.unmodifiableSet(supertypes);
  }

  /**
   * Given a method, return the methods that it overrides.
   *
   * @param method the overriding method
   * @return a map from types to methods that {@code method} overrides
   */
  public static Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods(
      Elements elements, AnnotatedTypeFactory atypeFactory, ExecutableElement method) {
    final TypeElement elem = (TypeElement) method.getEnclosingElement();
    final AnnotatedDeclaredType type = atypeFactory.getAnnotatedType(elem);
    final Collection<AnnotatedDeclaredType> supertypes = getSuperTypes(type);
    return overriddenMethods(elements, method, supertypes);
  }

  /**
   * Given a method and all supertypes (recursively) of the method's containing class, returns the
   * methods that the method overrides.
   *
   * @param method the overriding method
   * @param supertypes the set of supertypes to check for methods that are overridden by {@code
   *     method}
   * @return a map from types to methods that {@code method} overrides
   */
  public static Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods(
      Elements elements, ExecutableElement method, Collection<AnnotatedDeclaredType> supertypes) {

    Map<AnnotatedDeclaredType, ExecutableElement> overrides = new LinkedHashMap<>();

    for (AnnotatedDeclaredType supertype : supertypes) {
      @Nullable TypeElement superElement = (TypeElement) supertype.getUnderlyingType().asElement();
      assert superElement != null;
      // For all method in the supertype, add it to the set if
      // it overrides the given method.
      for (ExecutableElement supermethod :
          ElementFilter.methodsIn(superElement.getEnclosedElements())) {
        if (elements.overrides(method, supermethod, superElement)) {
          overrides.put(supertype, supermethod);
          break;
        }
      }
    }

    return Collections.unmodifiableMap(overrides);
  }

  /**
   * Given a method or constructor invocation, return a mapping of the type variables to their type
   * arguments, if any exist.
   *
   * <p>It uses the method or constructor invocation type arguments if they were specified and
   * otherwise it infers them based on the passed arguments or the return type context, according to
   * JLS 15.12.2.
   *
   * @param atypeFactory the annotated type factory
   * @param expr the method or constructor invocation tree; the passed argument has to be a subtype
   *     of MethodInvocationTree or NewClassTree
   * @param elt the element corresponding to the tree
   * @param preType the (partially annotated) type corresponding to the tree - the result of
   *     AnnotatedTypes.asMemberOf with the receiver and elt
   * @return the mapping of the type variables to type arguments for this method or constructor
   *     invocation
   */
  public static Map<TypeVariable, AnnotatedTypeMirror> findTypeArguments(
      final ProcessingEnvironment processingEnv,
      final AnnotatedTypeFactory atypeFactory,
      final ExpressionTree expr,
      final ExecutableElement elt,
      final AnnotatedExecutableType preType) {

    // Is the method a generic method?
    if (elt.getTypeParameters().isEmpty()) {
      return Collections.emptyMap();
    }

    List<? extends Tree> targs;
    if (expr instanceof MethodInvocationTree) {
      targs = ((MethodInvocationTree) expr).getTypeArguments();
    } else if (expr instanceof NewClassTree) {
      targs = ((NewClassTree) expr).getTypeArguments();
    } else if (expr instanceof MemberReferenceTree) {
      targs = ((MemberReferenceTree) expr).getTypeArguments();
      if (targs == null) {
        // TODO: Add type argument inference as part of fix for #979
        return new HashMap<>();
      }
    } else {
      // This case should never happen.
      throw new BugInCF("AnnotatedTypes.findTypeArguments: unexpected tree: " + expr);
    }

    // Has the user supplied type arguments?
    if (!targs.isEmpty()) {
      List<? extends AnnotatedTypeVariable> tvars = preType.getTypeVariables();

      Map<TypeVariable, AnnotatedTypeMirror> typeArguments = new HashMap<>();
      for (int i = 0; i < elt.getTypeParameters().size(); ++i) {
        AnnotatedTypeVariable typeVar = tvars.get(i);
        AnnotatedTypeMirror typeArg = atypeFactory.getAnnotatedTypeFromTypeTree(targs.get(i));
        // TODO: the call to getTypeParameterDeclaration shouldn't be necessary - typeVar
        // already should be a declaration.
        typeArguments.put(typeVar.getUnderlyingType(), typeArg);
      }
      return typeArguments;
    } else {
      return atypeFactory
          .getTypeArgumentInference()
          .inferTypeArgs(atypeFactory, expr, elt, preType);
    }
  }

  /**
   * Returns the lub of two annotated types.
   *
   * @param atypeFactory AnnotatedTypeFactory
   * @param type1 annotated type
   * @param type2 annotated type
   * @return the lub of type1 and type2
   */
  public static AnnotatedTypeMirror leastUpperBound(
      AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror type1, AnnotatedTypeMirror type2) {
    TypeMirror lub =
        TypesUtils.leastUpperBound(
            type1.getUnderlyingType(), type2.getUnderlyingType(), atypeFactory.getProcessingEnv());
    return leastUpperBound(atypeFactory, type1, type2, lub);
  }

  /**
   * Returns the lub, whose underlying type is {@code lubTypeMirror} of two annotated types.
   *
   * @param atypeFactory AnnotatedTypeFactory
   * @param type1 annotated type whose underlying type must be a subtype or convertible to
   *     lubTypeMirror
   * @param type2 annotated type whose underlying type must be a subtype or convertible to
   *     lubTypeMirror
   * @param lubTypeMirror underlying type of the returned lub
   * @return the lub of type1 and type2 with underlying type lubTypeMirror
   */
  public static AnnotatedTypeMirror leastUpperBound(
      AnnotatedTypeFactory atypeFactory,
      AnnotatedTypeMirror type1,
      AnnotatedTypeMirror type2,
      TypeMirror lubTypeMirror) {
    return new AtmLubVisitor(atypeFactory).lub(type1, type2, lubTypeMirror);
  }

  /**
   * Returns the method parameters for the invoked method, with the same number of arguments passed
   * in the methodInvocation tree.
   *
   * <p>If the invoked method is not a vararg method or it is a vararg method but the invocation
   * passes an array to the vararg parameter, it would simply return the method parameters.
   *
   * <p>Otherwise, it would return the list of parameters as if the vararg is expanded to match the
   * size of the passed arguments.
   *
   * @param method the method's type
   * @param args the arguments to the method invocation
   * @return the types that the method invocation arguments need to be subtype of
   */
  public static List<AnnotatedTypeMirror> expandVarArgs(
      AnnotatedTypeFactory atypeFactory,
      AnnotatedExecutableType method,
      List<? extends ExpressionTree> args) {
    List<AnnotatedTypeMirror> parameters = method.getParameterTypes();
    if (!method.getElement().isVarArgs()) {
      return parameters;
    }

    AnnotatedArrayType varargs = (AnnotatedArrayType) parameters.get(parameters.size() - 1);

    if (parameters.size() == args.size()) {
      // Check if one sent an element or an array
      AnnotatedTypeMirror lastArg = atypeFactory.getAnnotatedType(args.get(args.size() - 1));
      if (lastArg.getKind() == TypeKind.ARRAY
          && getArrayDepth(varargs) == getArrayDepth((AnnotatedArrayType) lastArg)) {
        return parameters;
      }
    }

    parameters = new ArrayList<>(parameters.subList(0, parameters.size() - 1));
    for (int i = args.size() - parameters.size(); i > 0; --i) {
      parameters.add(varargs.getComponentType().deepCopy());
    }

    return parameters;
  }

  public static List<AnnotatedTypeMirror> expandVarArgsFromTypes(
      AnnotatedExecutableType method, List<AnnotatedTypeMirror> args) {
    List<AnnotatedTypeMirror> parameters = method.getParameterTypes();
    if (!method.getElement().isVarArgs()) {
      return parameters;
    }

    AnnotatedArrayType varargs = (AnnotatedArrayType) parameters.get(parameters.size() - 1);

    if (parameters.size() == args.size()) {
      // Check if one sent an element or an array
      AnnotatedTypeMirror lastArg = args.get(args.size() - 1);
      if (lastArg.getKind() == TypeKind.ARRAY
          && (getArrayDepth(varargs) == getArrayDepth((AnnotatedArrayType) lastArg)
              // If the array depths don't match, but the component type of the vararg
              // is a type variable, then that type variable might later be
              // substituted for an array.
              || varargs.getComponentType().getKind() == TypeKind.TYPEVAR)) {
        return parameters;
      }
    }

    parameters = new ArrayList<>(parameters.subList(0, parameters.size() - 1));
    for (int i = args.size() - parameters.size(); i > 0; --i) {
      parameters.add(varargs.getComponentType());
    }

    return parameters;
  }

  /**
   * Given an AnnotatedExecutableType of a method or constructor declaration, get the parameter type
   * expected at the indexth position (unwrapping varargs if necessary).
   *
   * @param methodType AnnotatedExecutableType of method or constructor containing parameter to
   *     return
   * @param index position of parameter type to return
   * @return if that parameter is a varArgs, return the component of the var args and NOT the array
   *     type. Otherwise, return the exact type of the parameter in the index position.
   */
  public static AnnotatedTypeMirror getAnnotatedTypeMirrorOfParameter(
      AnnotatedExecutableType methodType, int index) {
    List<AnnotatedTypeMirror> parameterTypes = methodType.getParameterTypes();
    boolean hasVarArg = methodType.getElement().isVarArgs();

    final int lastIndex = parameterTypes.size() - 1;
    final AnnotatedTypeMirror lastType = parameterTypes.get(lastIndex);
    final boolean parameterBeforeVarargs = index < lastIndex;
    if (!parameterBeforeVarargs && lastType instanceof AnnotatedArrayType) {
      final AnnotatedArrayType arrayType = (AnnotatedArrayType) lastType;
      if (hasVarArg) {
        return arrayType.getComponentType();
      }
    }
    return parameterTypes.get(index);
  }

  /**
   * Return a list of the AnnotatedTypeMirror of the passed expression trees, in the same order as
   * the trees.
   *
   * @param paramTypes the parameter types to use as assignment context
   * @param trees the AST nodes
   * @return a list with the AnnotatedTypeMirror of each tree in trees
   */
  public static List<AnnotatedTypeMirror> getAnnotatedTypes(
      AnnotatedTypeFactory atypeFactory,
      List<AnnotatedTypeMirror> paramTypes,
      List<? extends ExpressionTree> trees) {
    if (paramTypes.size() != trees.size()) {
      throw new BugInCF(
          "AnnotatedTypes.getAnnotatedTypes: size mismatch! "
              + "Parameter types: "
              + paramTypes
              + " Arguments: "
              + trees);
    }
    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext =
        atypeFactory.getVisitorState().getAssignmentContext();

    List<AnnotatedTypeMirror> types = new ArrayList<>();
    try {
      for (int i = 0; i < trees.size(); ++i) {
        AnnotatedTypeMirror param = paramTypes.get(i);
        atypeFactory.getVisitorState().setAssignmentContext(Pair.of((Tree) null, param));
        ExpressionTree arg = trees.get(i);
        types.add(atypeFactory.getAnnotatedType(arg));
      }
    } finally {
      atypeFactory.getVisitorState().setAssignmentContext(preAssignmentContext);
    }
    return types;
  }

  /**
   * Returns the depth of the array type of the provided array.
   *
   * @param array the type of the array
   * @return the depth of the provided array
   */
  public static int getArrayDepth(AnnotatedArrayType array) {
    int counter = 0;
    AnnotatedTypeMirror type = array;
    while (type.getKind() == TypeKind.ARRAY) {
      counter++;
      type = ((AnnotatedArrayType) type).getComponentType();
    }
    return counter;
  }

  // The innermost *array* type.
  public static AnnotatedTypeMirror innerMostType(AnnotatedTypeMirror t) {
    AnnotatedTypeMirror inner = t;
    while (inner.getKind() == TypeKind.ARRAY) {
      inner = ((AnnotatedArrayType) inner).getComponentType();
    }
    return inner;
  }

  /**
   * Checks whether type contains the given modifier, also recursively in type arguments and arrays.
   * This method might be easier to implement directly as instance method in AnnotatedTypeMirror; it
   * corresponds to a "deep" version of {@link AnnotatedTypeMirror#hasAnnotation(AnnotationMirror)}.
   *
   * @param type the type to search
   * @param modifier the modifier to search for
   * @return whether the type contains the modifier
   */
  public static boolean containsModifier(AnnotatedTypeMirror type, AnnotationMirror modifier) {
    return containsModifierImpl(type, modifier, new ArrayList<>());
  }

  /*
   * For type variables we might hit the same type again. We keep a list of visited types.
   */
  private static boolean containsModifierImpl(
      AnnotatedTypeMirror type, AnnotationMirror modifier, List<AnnotatedTypeMirror> visited) {
    boolean found = type.hasAnnotation(modifier);
    boolean vis = visited.contains(type);
    visited.add(type);

    if (!found && !vis) {
      if (type.getKind() == TypeKind.DECLARED) {
        AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) type;
        for (AnnotatedTypeMirror typeMirror : declaredType.getTypeArguments()) {
          found |= containsModifierImpl(typeMirror, modifier, visited);
          if (found) {
            break;
          }
        }
      } else if (type.getKind() == TypeKind.ARRAY) {
        AnnotatedArrayType arrayType = (AnnotatedArrayType) type;
        found = containsModifierImpl(arrayType.getComponentType(), modifier, visited);
      } else if (type.getKind() == TypeKind.TYPEVAR) {
        AnnotatedTypeVariable atv = (AnnotatedTypeVariable) type;
        if (atv.getUpperBound() != null) {
          found = containsModifierImpl(atv.getUpperBound(), modifier, visited);
        }
        if (!found && atv.getLowerBound() != null) {
          found = containsModifierImpl(atv.getLowerBound(), modifier, visited);
        }
      } else if (type.getKind() == TypeKind.WILDCARD) {
        AnnotatedWildcardType awc = (AnnotatedWildcardType) type;
        if (awc.getExtendsBound() != null) {
          found = containsModifierImpl(awc.getExtendsBound(), modifier, visited);
        }
        if (!found && awc.getSuperBound() != null) {
          found = containsModifierImpl(awc.getSuperBound(), modifier, visited);
        }
      }
    }

    return found;
  }

  /** java.lang.annotation.Annotation.class canonical name. */
  private static @CanonicalName String annotationClassName =
      java.lang.annotation.Annotation.class.getCanonicalName();

  /**
   * Returns true if the underlying type of this atm is a java.lang.annotation.Annotation.
   *
   * @return true if the underlying type of this atm is a java.lang.annotation.Annotation
   */
  public static boolean isJavaLangAnnotation(final AnnotatedTypeMirror atm) {
    return TypesUtils.isDeclaredOfName(atm.getUnderlyingType(), annotationClassName);
  }

  /**
   * Returns true if atm is an Annotation interface, i.e., an implementation of
   * java.lang.annotation.Annotation. Given {@code @interface MyAnno}, a call to {@code
   * implementsAnnotation} returns true when called on an AnnotatedDeclaredType representing a use
   * of MyAnno.
   *
   * @return true if atm is an Annotation interface
   */
  public static boolean implementsAnnotation(final AnnotatedTypeMirror atm) {
    if (atm.getKind() != TypeKind.DECLARED) {
      return false;
    }
    final AnnotatedTypeMirror.AnnotatedDeclaredType declaredType =
        (AnnotatedTypeMirror.AnnotatedDeclaredType) atm;

    Symbol.ClassSymbol classSymbol =
        (Symbol.ClassSymbol) declaredType.getUnderlyingType().asElement();
    for (final Type iface : classSymbol.getInterfaces()) {
      if (TypesUtils.isDeclaredOfName(iface, annotationClassName)) {
        return true;
      }
    }

    return false;
  }

  public static boolean isEnum(final AnnotatedTypeMirror typeMirror) {
    if (typeMirror.getKind() == TypeKind.DECLARED) {
      final AnnotatedDeclaredType adt = (AnnotatedDeclaredType) typeMirror;
      return TypesUtils.isDeclaredOfName(adt.getUnderlyingType(), java.lang.Enum.class.getName());
    }

    return false;
  }

  public static boolean isDeclarationOfJavaLangEnum(
      final Types types, final Elements elements, final AnnotatedTypeMirror typeMirror) {
    if (isEnum(typeMirror)) {
      return elements
          .getTypeElement(Enum.class.getCanonicalName())
          .equals(((AnnotatedDeclaredType) typeMirror).getUnderlyingType().asElement());
    }

    return false;
  }

  /**
   * Returns true if the typeVar1 and typeVar2 are two uses of the same type variable.
   *
   * @return true if the typeVar1 and typeVar2 are two uses of the same type variable
   */
  public static boolean haveSameDeclaration(
      Types types, final AnnotatedTypeVariable typeVar1, final AnnotatedTypeVariable typeVar2) {
    return types.isSameType(typeVar1.getUnderlyingType(), typeVar2.getUnderlyingType());
  }

  /**
   * When overriding a method, you must include the same number of type parameters as the base
   * method. By index, these parameters are considered equivalent to the type parameters of the
   * overridden method. Necessary conditions: Both type variables are defined in methods One of the
   * two methods overrides the other Within their method declaration, both types have the same type
   * parameter index
   *
   * @return true if type1 and type2 are corresponding type variables (that is, either one
   *     "overrides" the other)
   */
  public static boolean areCorrespondingTypeVariables(
      Elements elements, AnnotatedTypeVariable type1, AnnotatedTypeVariable type2) {
    final TypeParameterElement type1ParamElem =
        (TypeParameterElement) type1.getUnderlyingType().asElement();
    final TypeParameterElement type2ParamElem =
        (TypeParameterElement) type2.getUnderlyingType().asElement();

    if (type1ParamElem.getGenericElement() instanceof ExecutableElement
        && type2ParamElem.getGenericElement() instanceof ExecutableElement) {
      final ExecutableElement type1Executable =
          (ExecutableElement) type1ParamElem.getGenericElement();
      final ExecutableElement type2Executable =
          (ExecutableElement) type2ParamElem.getGenericElement();

      final TypeElement type1Class = (TypeElement) type1Executable.getEnclosingElement();
      final TypeElement type2Class = (TypeElement) type2Executable.getEnclosingElement();

      boolean methodIsOverriden =
          elements.overrides(type1Executable, type2Executable, type1Class)
              || elements.overrides(type2Executable, type1Executable, type2Class);
      if (methodIsOverriden) {
        boolean haveSameIndex =
            type1Executable.getTypeParameters().indexOf(type1ParamElem)
                == type2Executable.getTypeParameters().indexOf(type2ParamElem);
        return haveSameIndex;
      }
    }

    return false;
  }

  /**
   * When comparing types against the bounds of a type variable, we may encounter other type
   * variables, wildcards, and intersections in those bounds. This method traverses the bounds until
   * it finds a concrete type from which it can pull an annotation.
   *
   * @param top the top of the hierarchy for which you are searching
   * @return the AnnotationMirror that represents the type of toSearch in the hierarchy of top
   */
  public static AnnotationMirror findEffectiveAnnotationInHierarchy(
      final QualifierHierarchy qualifierHierarchy,
      final AnnotatedTypeMirror toSearch,
      final AnnotationMirror top) {
    return findEffectiveAnnotationInHierarchy(qualifierHierarchy, toSearch, top, false);
  }

  /**
   * When comparing types against the bounds of a type variable, we may encounter other type
   * variables, wildcards, and intersections in those bounds. This method traverses the bounds until
   * it finds a concrete type from which it can pull an annotation.
   *
   * @param top the top of the hierarchy for which you are searching
   * @param canBeEmpty whether or not the effective type can have NO annotation in the hierarchy
   *     specified by top If this param is false, an exception will be thrown if no annotation is
   *     found Otherwise the result is null
   * @return the AnnotationMirror that represents the type of toSearch in the hierarchy of top
   */
  public static AnnotationMirror findEffectiveAnnotationInHierarchy(
      final QualifierHierarchy qualifierHierarchy,
      final AnnotatedTypeMirror toSearch,
      final AnnotationMirror top,
      final boolean canBeEmpty) {
    AnnotatedTypeMirror source = toSearch;
    while (source.getAnnotationInHierarchy(top) == null) {

      switch (source.getKind()) {
        case TYPEVAR:
          source = ((AnnotatedTypeVariable) source).getUpperBound();
          break;

        case WILDCARD:
          source = ((AnnotatedWildcardType) source).getExtendsBound();
          break;

        case INTERSECTION:
          // if there are multiple conflicting annotations, choose the lowest
          final AnnotationMirror glb =
              glbOfBoundsInHierarchy((AnnotatedIntersectionType) source, top, qualifierHierarchy);

          if (glb == null) {
            throw new BugInCF(
                "AnnotatedIntersectionType has no annotation in hierarchy "
                    + "on any of its supertypes."
                    + System.lineSeparator()
                    + "intersectionType="
                    + source);
          }
          return glb;

        default:
          if (canBeEmpty) {
            return null;
          }

          throw new BugInCF(
              StringsPlume.joinLines(
                  "Unexpected AnnotatedTypeMirror with no primary annotation.",
                  "toSearch=" + toSearch,
                  "top=" + top,
                  "source=" + source));
      }
    }

    return source.getAnnotationInHierarchy(top);
  }

  /**
   * When comparing types against the bounds of a type variable, we may encounter other type
   * variables, wildcards, and intersections in those bounds. This method traverses the lower bounds
   * until it finds a concrete type from which it can pull an annotation. This occurs for every
   * hierarchy in QualifierHierarchy
   *
   * @return the set of effective annotation mirrors in all hierarchies
   */
  public static Set<AnnotationMirror> findEffectiveLowerBoundAnnotations(
      final QualifierHierarchy qualifierHierarchy, final AnnotatedTypeMirror toSearch) {
    AnnotatedTypeMirror source = toSearch;
    TypeKind kind = source.getKind();
    while (kind == TypeKind.TYPEVAR || kind == TypeKind.WILDCARD || kind == TypeKind.INTERSECTION) {

      switch (source.getKind()) {
        case TYPEVAR:
          source = ((AnnotatedTypeVariable) source).getLowerBound();
          break;

        case WILDCARD:
          source = ((AnnotatedWildcardType) source).getSuperBound();
          break;

        case INTERSECTION:
          // if there are multiple conflicting annotations, choose the lowest
          final Set<AnnotationMirror> glb =
              glbOfBounds((AnnotatedIntersectionType) source, qualifierHierarchy);
          return glb;

        default:
          throw new BugInCF(
              "Unexpected AnnotatedTypeMirror with no primary annotation;"
                  + " toSearch="
                  + toSearch
                  + " source="
                  + source);
      }

      kind = source.getKind();
    }

    return source.getAnnotations();
  }

  /**
   * When comparing types against the bounds of a type variable, we may encounter other type
   * variables, wildcards, and intersections in those bounds. This method traverses the bounds until
   * it finds a concrete type from which it can pull an annotation. This occurs for every hierarchy
   * in QualifierHierarchy
   *
   * @return the set of effective annotation mirrors in all hierarchies
   */
  public static Set<AnnotationMirror> findEffectiveAnnotations(
      final QualifierHierarchy qualifierHierarchy, final AnnotatedTypeMirror toSearch) {
    AnnotatedTypeMirror source = toSearch;
    TypeKind kind = source.getKind();
    while (kind == TypeKind.TYPEVAR || kind == TypeKind.WILDCARD || kind == TypeKind.INTERSECTION) {

      switch (source.getKind()) {
        case TYPEVAR:
          source = ((AnnotatedTypeVariable) source).getUpperBound();
          break;

        case WILDCARD:
          source = ((AnnotatedWildcardType) source).getExtendsBound();
          break;

        case INTERSECTION:
          // if there are multiple conflicting annotations, choose the lowest
          final Set<AnnotationMirror> glb =
              glbOfBounds((AnnotatedIntersectionType) source, qualifierHierarchy);
          return glb;

        default:
          throw new BugInCF(
              "Unexpected AnnotatedTypeMirror with no primary annotation;"
                  + " toSearch="
                  + toSearch
                  + " source="
                  + source);
      }

      kind = source.getKind();
    }

    return source.getAnnotations();
  }

  private static AnnotationMirror glbOfBoundsInHierarchy(
      final AnnotatedIntersectionType isect,
      final AnnotationMirror top,
      final QualifierHierarchy qualifierHierarchy) {
    AnnotationMirror anno = isect.getAnnotationInHierarchy(top);
    for (AnnotatedTypeMirror bound : isect.getBounds()) {
      AnnotationMirror boundAnno = bound.getAnnotationInHierarchy(top);
      if (boundAnno != null && (anno == null || qualifierHierarchy.isSubtype(boundAnno, anno))) {
        anno = boundAnno;
      }
    }

    return anno;
  }

  /**
   * Gets the lowest primary annotation of all bounds in the intersection.
   *
   * @param isect the intersection for which we are glbing bounds
   * @param qualifierHierarchy the qualifier used to get the hierarchies in which to glb
   * @return a set of annotations representing the glb of the intersection's bounds
   */
  public static Set<AnnotationMirror> glbOfBounds(
      final AnnotatedIntersectionType isect, final QualifierHierarchy qualifierHierarchy) {
    Set<AnnotationMirror> result = AnnotationUtils.createAnnotationSet();
    for (final AnnotationMirror top : qualifierHierarchy.getTopAnnotations()) {
      final AnnotationMirror glbAnno = glbOfBoundsInHierarchy(isect, top, qualifierHierarchy);
      if (glbAnno != null) {
        result.add(glbAnno);
      }
    }

    return result;
  }

  // For Wildcards, isSuperBound and isExtendsBound will return true if isUnbound does.

  public static boolean isExplicitlySuperBounded(final AnnotatedWildcardType wildcardType) {
    return ((Type.WildcardType) wildcardType.getUnderlyingType()).isSuperBound()
        && !((Type.WildcardType) wildcardType.getUnderlyingType()).isUnbound();
  }

  /** Returns true if wildcard type was explicitly unbounded. */
  public static boolean isExplicitlyExtendsBounded(final AnnotatedWildcardType wildcardType) {
    return ((Type.WildcardType) wildcardType.getUnderlyingType()).isExtendsBound()
        && !((Type.WildcardType) wildcardType.getUnderlyingType()).isUnbound();
  }

  /** Returns true if this type is super bounded or unbounded. */
  public static boolean isUnboundedOrSuperBounded(final AnnotatedWildcardType wildcardType) {
    return ((Type.WildcardType) wildcardType.getUnderlyingType()).isSuperBound();
  }

  /** Returns true if this type is extends bounded or unbounded. */
  public static boolean isUnboundedOrExtendsBounded(final AnnotatedWildcardType wildcardType) {
    return ((Type.WildcardType) wildcardType.getUnderlyingType()).isExtendsBound();
  }

  /**
   * Copies explicit annotations and annotations resulting from resolution of polymorphic qualifiers
   * from {@code constructor} to {@code returnType}. If {@code returnType} has an annotation in the
   * same hierarchy of an annotation to be copied, that annotation is not copied.
   *
   * @param atypeFactory type factory
   * @param returnType return type to copy annotations to
   * @param constructor the ATM for the constructor
   */
  public static void copyOnlyExplicitConstructorAnnotations(
      AnnotatedTypeFactory atypeFactory,
      AnnotatedDeclaredType returnType,
      AnnotatedExecutableType constructor) {

    // TODO: There will be a nicer way to access this in 308 soon.
    List<Attribute.TypeCompound> decall =
        ((Symbol) constructor.getElement()).getRawTypeAttributes();
    Set<AnnotationMirror> decret = AnnotationUtils.createAnnotationSet();
    for (Attribute.TypeCompound da : decall) {
      if (da.position.type == com.sun.tools.javac.code.TargetType.METHOD_RETURN) {
        decret.add(da);
      }
    }

    // Collect all polymorphic qualifiers; we should substitute them.
    Set<AnnotationMirror> polys = AnnotationUtils.createAnnotationSet();
    for (AnnotationMirror anno : returnType.getAnnotations()) {
      if (atypeFactory.getQualifierHierarchy().isPolymorphicQualifier(anno)) {
        polys.add(anno);
      }
    }

    for (AnnotationMirror cta : constructor.getReturnType().getAnnotations()) {
      AnnotationMirror ctatop = atypeFactory.getQualifierHierarchy().getTopAnnotation(cta);
      if (returnType.isAnnotatedInHierarchy(cta)) {
        continue;
      }
      if (atypeFactory.isSupportedQualifier(cta) && !returnType.isAnnotatedInHierarchy(cta)) {
        for (AnnotationMirror fromDecl : decret) {
          if (atypeFactory.isSupportedQualifier(fromDecl)
              && AnnotationUtils.areSame(
                  ctatop, atypeFactory.getQualifierHierarchy().getTopAnnotation(fromDecl))) {
            returnType.addAnnotation(cta);
            break;
          }
        }
      }

      // Go through the polymorphic qualifiers and see whether
      // there is anything left to replace.
      for (AnnotationMirror pa : polys) {
        if (AnnotationUtils.areSame(
            ctatop, atypeFactory.getQualifierHierarchy().getTopAnnotation(pa))) {
          returnType.replaceAnnotation(cta);
          break;
        }
      }
    }
  }

  /**
   * Add all the annotations in {@code declaredType} to {@code annotatedDeclaredType}.
   *
   * <p>(The {@code TypeMirror} returned by {@code annotatedDeclaredType#getUnderlyingType} may have
   * not have all the annotations on the type, so allow the user to specify a different one.)
   *
   * @param annotatedDeclaredType annotated type to which annotations are added
   * @param declaredType TypeMirror that may have annotations
   */
  public static void applyAnnotationsFromDeclaredType(
      AnnotatedDeclaredType annotatedDeclaredType, DeclaredType declaredType) {
    TypeMirror underlyingTypeMirror = declaredType;
    while (annotatedDeclaredType != null) {
      List<? extends AnnotationMirror> annosOnTypeMirror =
          underlyingTypeMirror.getAnnotationMirrors();
      annotatedDeclaredType.addAnnotations(annosOnTypeMirror);
      annotatedDeclaredType = annotatedDeclaredType.getEnclosingType();
      underlyingTypeMirror = ((DeclaredType) underlyingTypeMirror).getEnclosingType();
    }
  }
}
