package org.checkerframework.checker.initialization;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import org.checkerframework.checker.initialization.qual.FBCBottom;
import org.checkerframework.checker.initialization.qual.Initialized;
import org.checkerframework.checker.initialization.qual.NotOnlyInitialized;
import org.checkerframework.checker.initialization.qual.UnderInitialization;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.NullnessAnnotatedTypeFactory;
import org.checkerframework.checker.nullness.NullnessChecker;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAbstractValue;
import org.checkerframework.framework.qual.Unused;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.MostlyNoElementQualifierHierarchy;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.framework.type.typeannotator.ListTypeAnnotator;
import org.checkerframework.framework.type.typeannotator.TypeAnnotator;
import org.checkerframework.framework.util.QualifierKind;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;

/**
 * The annotated type factory for the freedom-before-commitment type-system. The
 * freedom-before-commitment type-system and this class are abstract and need to be combined with
 * another type-system whose safe initialization should be tracked. For an example, see the {@link
 * NullnessChecker}.
 */
public abstract class InitializationAnnotatedTypeFactory<
        Value extends CFAbstractValue<Value>,
        Store extends InitializationStore<Value, Store>,
        Transfer extends InitializationTransfer<Value, Transfer, Store>,
        Flow extends CFAbstractAnalysis<Value, Store, Transfer>>
    extends GenericAnnotatedTypeFactory<Value, Store, Transfer, Flow> {

  /** {@link UnknownInitialization}. */
  protected final AnnotationMirror UNKNOWN_INITIALIZATION;

  /** {@link Initialized}. */
  protected final AnnotationMirror INITIALIZED;

  /** {@link UnderInitialization} or null. */
  protected final AnnotationMirror UNDER_INITALIZATION;

  /** {@link NotOnlyInitialized} or null. */
  protected final AnnotationMirror NOT_ONLY_INITIALIZED;

  /** {@link FBCBottom}. */
  protected final AnnotationMirror FBCBOTTOM;

  /** The java.lang.Object type. */
  protected final TypeMirror objectTypeMirror;

  /** The Unused.when field/element. */
  protected final ExecutableElement unusedWhenElement;
  /** The UnderInitialization.value field/element. */
  protected final ExecutableElement underInitializationValueElement;
  /** The UnknownInitialization.value field/element. */
  protected final ExecutableElement unknownInitializationValueElement;

  /** Cache for the initialization annotations. */
  protected final Set<Class<? extends Annotation>> initAnnos;

  /**
   * String representation of all initialization annotations.
   *
   * <p>{@link UnknownInitialization} {@link UnderInitialization} {@link Initialized} {@link
   * FBCBottom}
   *
   * <p>This is used to quickly check of an AnnotationMirror is one of the initialization
   * annotations without having to repeatedly convert them to strings.
   */
  protected final Set<String> initAnnoNames;

  /**
   * Create a new InitializationAnnotatedTypeFactory.
   *
   * @param checker the checker to which the new type factory belongs
   */
  protected InitializationAnnotatedTypeFactory(BaseTypeChecker checker) {
    super(checker, true);

    UNKNOWN_INITIALIZATION = AnnotationBuilder.fromClass(elements, UnknownInitialization.class);
    INITIALIZED = AnnotationBuilder.fromClass(elements, Initialized.class);
    UNDER_INITALIZATION = AnnotationBuilder.fromClass(elements, UnderInitialization.class);
    NOT_ONLY_INITIALIZED = AnnotationBuilder.fromClass(elements, NotOnlyInitialized.class);
    FBCBOTTOM = AnnotationBuilder.fromClass(elements, FBCBottom.class);

    objectTypeMirror = processingEnv.getElementUtils().getTypeElement("java.lang.Object").asType();
    unusedWhenElement = TreeUtils.getMethod(Unused.class, "when", 0, processingEnv);
    underInitializationValueElement =
        TreeUtils.getMethod(UnderInitialization.class, "value", 0, processingEnv);
    unknownInitializationValueElement =
        TreeUtils.getMethod(UnknownInitialization.class, "value", 0, processingEnv);

    Set<Class<? extends Annotation>> tempInitAnnos = new LinkedHashSet<>(4);
    tempInitAnnos.add(UnderInitialization.class);
    tempInitAnnos.add(Initialized.class);
    tempInitAnnos.add(UnknownInitialization.class);
    tempInitAnnos.add(FBCBottom.class);

    initAnnos = Collections.unmodifiableSet(tempInitAnnos);

    Set<String> tempInitAnnoNames = new HashSet<>(4);
    tempInitAnnoNames.add(AnnotationUtils.annotationName(UNKNOWN_INITIALIZATION));
    tempInitAnnoNames.add(AnnotationUtils.annotationName(UNDER_INITALIZATION));
    tempInitAnnoNames.add(AnnotationUtils.annotationName(INITIALIZED));
    tempInitAnnoNames.add(AnnotationUtils.annotationName(FBCBOTTOM));

    initAnnoNames = Collections.unmodifiableSet(tempInitAnnoNames);

    // No call to postInit() because this class is abstract.
    // Its subclasses must call postInit().
  }

  public Set<Class<? extends Annotation>> getInitializationAnnotations() {
    return initAnnos;
  }

  /**
   * Is the annotation {@code anno} an initialization qualifier?
   *
   * @param anno the annotation to check
   * @return true if the argument is an initialization qualifier
   */
  protected boolean isInitializationAnnotation(AnnotationMirror anno) {
    assert anno != null;
    return initAnnoNames.contains(AnnotationUtils.annotationName(anno));
  }

  /*
   * The following method can be used to appropriately configure the
   * commitment type-system.
   */

  /**
   * Returns the list of annotations that is forbidden for the constructor return type.
   *
   * @return the list of annotations that is forbidden for the constructor return type
   */
  public Set<Class<? extends Annotation>> getInvalidConstructorReturnTypeAnnotations() {
    return getInitializationAnnotations();
  }

  /**
   * Returns the annotation that makes up the invariant of this commitment type system, such as
   * {@code @NonNull}.
   *
   * @return the invariant annotation for this type system
   */
  public abstract AnnotationMirror getFieldInvariantAnnotation();

  /**
   * Returns whether or not {@code field} has the invariant annotation.
   *
   * <p>This method is a convenience method for {@link
   * #hasFieldInvariantAnnotation(AnnotatedTypeMirror, VariableElement)}.
   *
   * <p>If the {@code field} is a type variable, this method returns true if any possible
   * instantiation of the type parameter could have the invariant annotation. See {@link
   * NullnessAnnotatedTypeFactory#hasFieldInvariantAnnotation(VariableTree)} for an example.
   *
   * @param field field that might have invariant annotation
   * @return whether or not field has the invariant annotation
   */
  protected final boolean hasFieldInvariantAnnotation(VariableTree field) {
    AnnotatedTypeMirror type = getAnnotatedType(field);
    VariableElement fieldElement = TreeUtils.elementFromDeclaration(field);
    return hasFieldInvariantAnnotation(type, fieldElement);
  }

  /**
   * Returns whether or not {@code type} has the invariant annotation.
   *
   * <p>If the {@code type} is a type variable, this method returns true if any possible
   * instantiation of the type parameter could have the invariant annotation. See {@link
   * NullnessAnnotatedTypeFactory#hasFieldInvariantAnnotation(VariableTree)} for an example.
   *
   * @param type of field that might have invariant annotation
   * @param fieldElement the field element, which can be used to check annotations on the
   *     declaration
   * @return whether or not the type has the invariant annotation
   */
  protected abstract boolean hasFieldInvariantAnnotation(
      AnnotatedTypeMirror type, VariableElement fieldElement);

  /**
   * Creates a {@link UnderInitialization} annotation with the given type as its type frame
   * argument.
   *
   * @param typeFrame the type down to which some value has been initialized
   * @return an {@link UnderInitialization} annotation with the given argument
   */
  public AnnotationMirror createUnderInitializationAnnotation(TypeMirror typeFrame) {
    assert typeFrame != null;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, UnderInitialization.class);
    builder.setValue("value", typeFrame);
    return builder.build();
  }

  /**
   * Creates a {@link UnderInitialization} annotation with the given type frame.
   *
   * @param typeFrame the type down to which some value has been initialized
   * @return an {@link UnderInitialization} annotation with the given argument
   */
  public AnnotationMirror createUnderInitializationAnnotation(Class<?> typeFrame) {
    assert typeFrame != null;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, UnderInitialization.class);
    builder.setValue("value", typeFrame);
    return builder.build();
  }

  /**
   * Creates a {@link UnknownInitialization} annotation with a given type frame.
   *
   * @param typeFrame the type down to which some value has been initialized
   * @return an {@link UnknownInitialization} annotation with the given argument
   */
  public AnnotationMirror createUnknownInitializationAnnotation(Class<?> typeFrame) {
    assert typeFrame != null;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, UnknownInitialization.class);
    builder.setValue("value", typeFrame);
    return builder.build();
  }

  /**
   * Creates an {@link UnknownInitialization} annotation with a given type frame.
   *
   * @param typeFrame the type down to which some value has been initialized
   * @return an {@link UnknownInitialization} annotation with the given argument
   */
  public AnnotationMirror createUnknownInitializationAnnotation(TypeMirror typeFrame) {
    assert typeFrame != null;
    AnnotationBuilder builder = new AnnotationBuilder(processingEnv, UnknownInitialization.class);
    builder.setValue("value", typeFrame);
    return builder.build();
  }

  /**
   * Returns the type frame (that is, the argument) of a given initialization annotation.
   *
   * @param annotation a {@link UnderInitialization} or {@link UnknownInitialization} annotation
   * @return the annotation's argument
   */
  public TypeMirror getTypeFrameFromAnnotation(AnnotationMirror annotation) {
    if (AnnotationUtils.areSameByName(
        annotation, "org.checkerframework.checker.initialization.qual.UnderInitialization")) {
      return AnnotationUtils.getElementValue(
          annotation, underInitializationValueElement, TypeMirror.class, objectTypeMirror);
    } else {
      return AnnotationUtils.getElementValue(
          annotation, unknownInitializationValueElement, TypeMirror.class, objectTypeMirror);
    }
  }

  /**
   * Is {@code anno} the {@link UnderInitialization} annotation (with any type frame)?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} is {@link UnderInitialization}
   */
  public boolean isUnderInitialization(AnnotationMirror anno) {
    return areSameByClass(anno, UnderInitialization.class);
  }

  /**
   * Is {@code anno} the {@link UnknownInitialization} annotation (with any type frame)?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} is {@link UnknownInitialization}
   */
  public boolean isUnknownInitialization(AnnotationMirror anno) {
    return areSameByClass(anno, UnknownInitialization.class);
  }

  /**
   * Is {@code anno} the bottom annotation?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} is {@link FBCBottom}
   */
  public boolean isFbcBottom(AnnotationMirror anno) {
    return AnnotationUtils.areSame(anno, FBCBOTTOM);
  }

  /**
   * Is {@code anno} the {@link Initialized} annotation?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} is {@link Initialized}
   */
  public boolean isInitialized(AnnotationMirror anno) {
    return AnnotationUtils.areSame(anno, INITIALIZED);
  }

  /**
   * Does {@code anno} have the annotation {@link UnderInitialization} (with any type frame)?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} has {@link UnderInitialization}
   */
  public boolean isUnderInitialization(AnnotatedTypeMirror anno) {
    return anno.hasEffectiveAnnotation(UnderInitialization.class);
  }

  /**
   * Does {@code anno} have the annotation {@link UnknownInitialization} (with any type frame)?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} has {@link UnknownInitialization}
   */
  public boolean isUnknownInitialization(AnnotatedTypeMirror anno) {
    return anno.hasEffectiveAnnotation(UnknownInitialization.class);
  }

  /**
   * Does {@code anno} have the bottom annotation?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} has {@link FBCBottom}
   */
  public boolean isFbcBottom(AnnotatedTypeMirror anno) {
    return anno.hasEffectiveAnnotation(FBCBottom.class);
  }

  /**
   * Does {@code anno} have the annotation {@link Initialized}?
   *
   * @param anno the annotation to check
   * @return true if {@code anno} has {@link Initialized}
   */
  public boolean isInitialized(AnnotatedTypeMirror anno) {
    return anno.hasEffectiveAnnotation(Initialized.class);
  }

  /**
   * Are all fields initialized-only?
   *
   * @param classTree the class to query
   * @return true if all fields are initialized-only
   */
  protected boolean areAllFieldsInitializedOnly(ClassTree classTree) {
    for (Tree member : classTree.getMembers()) {
      if (member.getKind() != Tree.Kind.VARIABLE) {
        continue;
      }
      VariableTree var = (VariableTree) member;
      VariableElement varElt = TreeUtils.elementFromDeclaration(var);
      // var is not initialized-only
      if (getDeclAnnotation(varElt, NotOnlyInitialized.class) != null) {
        // var is not static -- need a check of initializer blocks,
        // not of constructor which is where this is used
        if (!varElt.getModifiers().contains(Modifier.STATIC)) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * {@inheritDoc}
   *
   * <p>In most cases, subclasses want to call this method first because it may clear all
   * annotations and use the hierarchy's root annotations.
   */
  @Override
  public void postAsMemberOf(AnnotatedTypeMirror type, AnnotatedTypeMirror owner, Element element) {
    super.postAsMemberOf(type, owner, element);

    if (element.getKind().isField()) {
      Collection<? extends AnnotationMirror> declaredFieldAnnotations = getDeclAnnotations(element);
      AnnotatedTypeMirror fieldAnnotations = getAnnotatedType(element);
      computeFieldAccessType(type, declaredFieldAnnotations, owner, fieldAnnotations, element);
    }
  }

  /**
   * Controls which hierarchies' qualifiers are changed based on the receiver type and the declared
   * annotations for a field.
   *
   * @see #computeFieldAccessType
   * @see #getAnnotatedTypeLhs(Tree)
   */
  private boolean computingAnnotatedTypeMirrorOfLHS = false;

  @Override
  public AnnotatedTypeMirror getAnnotatedTypeLhs(Tree lhsTree) {
    boolean oldComputingAnnotatedTypeMirrorOfLHS = computingAnnotatedTypeMirrorOfLHS;
    computingAnnotatedTypeMirrorOfLHS = true;
    AnnotatedTypeMirror result = super.getAnnotatedTypeLhs(lhsTree);
    computingAnnotatedTypeMirrorOfLHS = oldComputingAnnotatedTypeMirrorOfLHS;
    return result;
  }

  @Override
  public AnnotatedDeclaredType getSelfType(Tree tree) {
    AnnotatedDeclaredType selfType = super.getSelfType(tree);

    TreePath path = getPath(tree);
    AnnotatedDeclaredType enclosing = selfType;
    while (path != null && enclosing != null) {
      TreePath topLevelMemberPath = findTopLevelClassMemberForTree(path);
      if (topLevelMemberPath != null && topLevelMemberPath.getLeaf() != null) {
        Tree topLevelMember = topLevelMemberPath.getLeaf();
        if (topLevelMember.getKind() != Kind.METHOD
            || TreeUtils.isConstructor((MethodTree) topLevelMember)) {
          setSelfTypeInInitializationCode(tree, enclosing, topLevelMemberPath);
        }
        path = topLevelMemberPath.getParentPath();
        enclosing = enclosing.getEnclosingType();
      } else {
        break;
      }
    }

    return selfType;
  }

  /**
   * In the first enclosing class, find the path to the top-level member that contains {@code path}.
   *
   * @param path the path whose leaf is the target
   * @return path to a top-level member containing the leaf of {@code path}
   */
  @SuppressWarnings("interning:not.interned") // AST node comparison
  private TreePath findTopLevelClassMemberForTree(TreePath path) {
    if (TreeUtils.isClassTree(path.getLeaf())) {
      path = path.getParentPath();
      if (path == null) {
        return null;
      }
    }
    ClassTree enclosingClass = TreePathUtil.enclosingClass(path);
    if (enclosingClass != null) {
      List<? extends Tree> classMembers = enclosingClass.getMembers();
      TreePath searchPath = path;
      while (searchPath.getParentPath() != null
          && searchPath.getParentPath().getLeaf() != enclosingClass) {
        searchPath = searchPath.getParentPath();
        if (classMembers.contains(searchPath.getLeaf())) {
          return searchPath;
        }
      }
    }
    return null;
  }

  /**
   * Side-effects argument {@code selfType} to make it @Initialized or @UnderInitialization,
   * depending on whether all fields have been set.
   *
   * @param tree a tree
   * @param selfType the type to side-effect
   * @param path a path
   */
  protected void setSelfTypeInInitializationCode(
      Tree tree, AnnotatedDeclaredType selfType, TreePath path) {
    ClassTree enclosingClass = TreePathUtil.enclosingClass(path);
    Type classType = ((JCTree) enclosingClass).type;
    AnnotationMirror annotation = null;

    // If all fields are initialized-only, and they are all initialized,
    // then:
    //  - if the class is final, this is @Initialized
    //  - otherwise, this is @UnderInitialization(CurrentClass) as
    //    there might still be subclasses that need initialization.
    if (areAllFieldsInitializedOnly(enclosingClass)) {
      Store store = getStoreBefore(tree);
      if (store != null
          && getUninitializedInvariantFields(store, path, false, Collections.emptyList())
              .isEmpty()) {
        if (classType.isFinal()) {
          annotation = INITIALIZED;
        } else {
          annotation = createUnderInitializationAnnotation(classType);
        }
      }
    }

    if (annotation == null) {
      annotation = getUnderInitializationAnnotationOfSuperType(classType);
    }
    selfType.replaceAnnotation(annotation);
  }

  /**
   * Returns an {@link UnderInitialization} annotation that has the superclass of {@code type} as
   * type frame.
   *
   * @param type a type
   * @return true an {@link UnderInitialization} for the supertype of {@code type}
   */
  protected AnnotationMirror getUnderInitializationAnnotationOfSuperType(TypeMirror type) {
    // Find supertype if possible.
    AnnotationMirror annotation;
    List<? extends TypeMirror> superTypes = types.directSupertypes(type);
    TypeMirror superClass = null;
    for (TypeMirror superType : superTypes) {
      ElementKind kind = types.asElement(superType).getKind();
      if (kind == ElementKind.CLASS) {
        superClass = superType;
        break;
      }
    }
    // Create annotation.
    if (superClass != null) {
      annotation = createUnderInitializationAnnotation(superClass);
    } else {
      // Use Object as a valid super-class.
      annotation = createUnderInitializationAnnotation(Object.class);
    }
    return annotation;
  }

  /**
   * Returns the fields that are not yet initialized in a given store. The result is a pair of
   * lists:
   *
   * <ul>
   *   <li>fields that are not yet initialized and have the invariant annotation
   *   <li>fields that are not yet initialized and do not have the invariant annotation
   * </ul>
   *
   * @param store a store
   * @param path the current path, used to determine the current class
   * @param isStatic whether to report static fields or instance fields
   * @param receiverAnnotations the annotations on the receiver
   * @return the fields that are not yet initialized in a given store (a pair of lists)
   */
  public Pair<List<VariableTree>, List<VariableTree>> getUninitializedFields(
      Store store,
      TreePath path,
      boolean isStatic,
      Collection<? extends AnnotationMirror> receiverAnnotations) {
    ClassTree currentClass = TreePathUtil.enclosingClass(path);
    List<VariableTree> fields = InitializationChecker.getAllFields(currentClass);
    List<VariableTree> uninitWithInvariantAnno = new ArrayList<>();
    List<VariableTree> uninitWithoutInvariantAnno = new ArrayList<>();
    for (VariableTree field : fields) {
      if (isUnused(field, receiverAnnotations)) {
        continue; // don't consider unused fields
      }
      VariableElement fieldElem = TreeUtils.elementFromDeclaration(field);
      if (ElementUtils.isStatic(fieldElem) == isStatic) {
        // Has the field been initialized?
        if (!store.isFieldInitialized(fieldElem)) {
          // Does this field need to satisfy the invariant?
          if (hasFieldInvariantAnnotation(field)) {
            uninitWithInvariantAnno.add(field);
          } else {
            uninitWithoutInvariantAnno.add(field);
          }
        }
      }
    }
    return Pair.of(uninitWithInvariantAnno, uninitWithoutInvariantAnno);
  }

  /**
   * Returns the fields that have the invariant annotation and are not yet initialized in a given
   * store.
   *
   * @param store a store
   * @param path the current path, used to determine the current class
   * @param isStatic whether to report static fields or instance fields
   * @param receiverAnnotations the annotations on the receiver
   * @return the fields that have the invariant annotation and are not yet initialized in a given
   *     store (a pair of lists)
   */
  public final List<VariableTree> getUninitializedInvariantFields(
      Store store,
      TreePath path,
      boolean isStatic,
      List<? extends AnnotationMirror> receiverAnnotations) {
    return getUninitializedFields(store, path, isStatic, receiverAnnotations).first;
  }

  /**
   * Returns the fields that have the invariant annotation and are initialized in a given store.
   *
   * @param store a store
   * @param path the current path; used to compute the current class
   * @return the fields that have the invariant annotation and are initialized in a given store
   */
  public List<VariableTree> getInitializedInvariantFields(Store store, TreePath path) {
    // TODO: Instead of passing the TreePath around, can we use
    // getCurrentClassTree?
    ClassTree currentClass = TreePathUtil.enclosingClass(path);
    List<VariableTree> fields = InitializationChecker.getAllFields(currentClass);
    List<VariableTree> initializedFields = new ArrayList<>();
    for (VariableTree field : fields) {
      VariableElement fieldElem = TreeUtils.elementFromDeclaration(field);
      if (!ElementUtils.isStatic(fieldElem)) {
        // Does this field need to satisfy the invariant?
        if (hasFieldInvariantAnnotation(field)) {
          // Has the field been initialized?
          if (store.isFieldInitialized(fieldElem)) {
            initializedFields.add(field);
          }
        }
      }
    }
    return initializedFields;
  }

  /** Returns whether the field {@code f} is unused, given the annotations on the receiver. */
  private boolean isUnused(
      VariableTree field, Collection<? extends AnnotationMirror> receiverAnnos) {
    if (receiverAnnos.isEmpty()) {
      return false;
    }

    AnnotationMirror unused =
        getDeclAnnotation(TreeUtils.elementFromDeclaration(field), Unused.class);
    if (unused == null) {
      return false;
    }

    Name when = AnnotationUtils.getElementValueClassName(unused, unusedWhenElement);
    for (AnnotationMirror anno : receiverAnnos) {
      Name annoName = ((TypeElement) anno.getAnnotationType().asElement()).getQualifiedName();
      if (annoName.contentEquals(when)) {
        return true;
      }
    }

    return false;
  }

  /**
   * Return true if the type is initialized with respect to the given frame -- that is, all of the
   * fields of the frame are initialized.
   *
   * @param type the type whose initialization type qualifiers to check
   * @param frame a class in {@code type}'s class hierarchy
   * @return true if the type is initialized for the given frame
   */
  public boolean isInitializedForFrame(AnnotatedTypeMirror type, TypeMirror frame) {
    AnnotationMirror initializationAnno =
        type.getEffectiveAnnotationInHierarchy(UNKNOWN_INITIALIZATION);
    TypeMirror typeFrame = getTypeFrameFromAnnotation(initializationAnno);
    Types types = processingEnv.getTypeUtils();
    return types.isSubtype(typeFrame, types.erasure(frame));
  }

  /**
   * Determine the type of a field access (implicit or explicit) based on the receiver type and the
   * declared annotations for the field.
   *
   * @param type type of the field access expression
   * @param declaredFieldAnnotations annotations on the element
   * @param receiverType inferred annotations of the receiver
   */
  private void computeFieldAccessType(
      AnnotatedTypeMirror type,
      Collection<? extends AnnotationMirror> declaredFieldAnnotations,
      AnnotatedTypeMirror receiverType,
      AnnotatedTypeMirror fieldAnnotations,
      Element element) {
    // not necessary for primitive fields
    if (TypesUtils.isPrimitive(type.getUnderlyingType())) {
      return;
    }
    // not necessary if there is an explicit UnknownInitialization
    // annotation on the field
    if (AnnotationUtils.containsSameByName(
        fieldAnnotations.getAnnotations(), UNKNOWN_INITIALIZATION)) {
      return;
    }
    if (isUnknownInitialization(receiverType) || isUnderInitialization(receiverType)) {

      TypeMirror fieldDeclarationType = element.getEnclosingElement().asType();
      boolean isInitializedForFrame = isInitializedForFrame(receiverType, fieldDeclarationType);
      if (isInitializedForFrame) {
        // The receiver is initialized for this frame.
        // Change the type of the field to @UnknownInitialization so that
        // anything can be assigned to this field.
        type.replaceAnnotation(UNKNOWN_INITIALIZATION);
      } else if (computingAnnotatedTypeMirrorOfLHS) {
        // The receiver is not initialized for this frame, but the type of a lhs is being computed.
        // Change the type of the field to @UnknownInitialization so that
        // anything can be assigned to this field.
        type.replaceAnnotation(UNKNOWN_INITIALIZATION);
      } else {
        // The receiver is not initialized for this frame and the type being computed is not a LHS.
        // Replace all annotations with the top annotation for that hierarchy.
        type.clearAnnotations();
        type.addAnnotations(qualHierarchy.getTopAnnotations());
      }

      if (!AnnotationUtils.containsSame(declaredFieldAnnotations, NOT_ONLY_INITIALIZED)) {
        // add root annotation for all other hierarchies, and
        // Initialized for the initialization hierarchy
        type.replaceAnnotation(INITIALIZED);
      }
    }
  }

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

  @Override
  protected TreeAnnotator createTreeAnnotator() {
    return new ListTreeAnnotator(super.createTreeAnnotator(), new CommitmentTreeAnnotator(this));
  }

  protected class CommitmentTypeAnnotator extends TypeAnnotator {
    public CommitmentTypeAnnotator(InitializationAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory) {
      super(atypeFactory);
    }

    @Override
    public Void visitExecutable(AnnotatedExecutableType t, Void p) {
      Void result = super.visitExecutable(t, p);
      Element elem = t.getElement();
      if (elem.getKind() == ElementKind.CONSTRUCTOR) {
        AnnotatedDeclaredType returnType = (AnnotatedDeclaredType) t.getReturnType();
        DeclaredType underlyingType = returnType.getUnderlyingType();
        returnType.replaceAnnotation(getUnderInitializationAnnotationOfSuperType(underlyingType));
      }
      return result;
    }
  }

  protected class CommitmentTreeAnnotator extends TreeAnnotator {

    public CommitmentTreeAnnotator(InitializationAnnotatedTypeFactory<?, ?, ?, ?> atypeFactory) {
      super(atypeFactory);
    }

    @Override
    public Void visitMethod(MethodTree node, AnnotatedTypeMirror p) {
      Void result = super.visitMethod(node, p);
      if (TreeUtils.isConstructor(node)) {
        assert p instanceof AnnotatedExecutableType;
        AnnotatedExecutableType exeType = (AnnotatedExecutableType) p;
        DeclaredType underlyingType = (DeclaredType) exeType.getReturnType().getUnderlyingType();
        AnnotationMirror a = getUnderInitializationAnnotationOfSuperType(underlyingType);
        exeType.getReturnType().replaceAnnotation(a);
      }
      return result;
    }

    @Override
    public Void visitNewClass(NewClassTree node, AnnotatedTypeMirror p) {
      super.visitNewClass(node, p);
      boolean allInitialized = true;
      Type type = ((JCTree) node).type;
      for (ExpressionTree a : node.getArguments()) {
        final AnnotatedTypeMirror t = getAnnotatedType(a);
        allInitialized &= (isInitialized(t) || isFbcBottom(t));
      }
      if (!allInitialized) {
        p.replaceAnnotation(createUnderInitializationAnnotation(type));
        return null;
      }
      p.replaceAnnotation(INITIALIZED);
      return null;
    }

    @Override
    public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) {
      if (tree.getKind() != Tree.Kind.NULL_LITERAL) {
        type.addAnnotation(INITIALIZED);
      }
      return super.visitLiteral(tree, type);
    }

    @Override
    public Void visitMemberSelect(MemberSelectTree node, AnnotatedTypeMirror annotatedTypeMirror) {
      if (TreeUtils.isArrayLengthAccess(node)) {
        annotatedTypeMirror.replaceAnnotation(INITIALIZED);
      }
      return super.visitMemberSelect(node, annotatedTypeMirror);
    }
  }

  /**
   * The {@link QualifierHierarchy} for the initialization type system.
   *
   * <p>Type systems extending the Initialization Checker should call methods {@link
   * InitializationQualifierHierarchy#isSubtypeInitialization} and {@link
   * InitializationQualifierHierarchy#leastUpperBoundInitialization} for appropriate qualifiers. See
   * protected subclass NullnessQualifierHierarchy within class {@link NullnessChecker} for an
   * example.
   */
  protected abstract class InitializationQualifierHierarchy
      extends MostlyNoElementQualifierHierarchy {

    /** Qualifier kind for the @{@link UnknownInitialization} annotation. */
    private final QualifierKind UNKNOWN_INIT;
    /** Qualifier kind for the @{@link UnderInitialization} annotation. */
    private final QualifierKind UNDER_INIT;

    /** Create an InitializationQualifierHierarchy. */
    protected InitializationQualifierHierarchy() {
      super(InitializationAnnotatedTypeFactory.this.getSupportedTypeQualifiers(), elements);
      UNKNOWN_INIT = getQualifierKind(UNKNOWN_INITIALIZATION);
      UNDER_INIT = getQualifierKind(UNDER_INITALIZATION);
    }

    /**
     * Subtype testing for initialization annotations. Will return false if either qualifier is not
     * an initialization annotation. Subclasses should override isSubtype and call this method for
     * initialization qualifiers.
     *
     * @param subAnno subtype annotation
     * @param subKind subtype kind
     * @param superAnno supertype annotation
     * @param superKind supertype kind
     * @return true if subAnno is a subtype of superAnno in the initialization hierarchy
     */
    public boolean isSubtypeInitialization(
        AnnotationMirror subAnno,
        QualifierKind subKind,
        AnnotationMirror superAnno,
        QualifierKind superKind) {
      if (!subKind.isSubtypeOf(superKind)) {
        return false;
      } else if ((subKind == UNDER_INIT && superKind == UNDER_INIT)
          || (subKind == UNDER_INIT && superKind == UNKNOWN_INIT)
          || (subKind == UNKNOWN_INIT && superKind == UNKNOWN_INIT)) {
        // Thus, we only need to look at the type frame.
        TypeMirror frame1 = getTypeFrameFromAnnotation(subAnno);
        TypeMirror frame2 = getTypeFrameFromAnnotation(superAnno);
        return types.isSubtype(frame1, frame2);
      } else {
        return true;
      }
    }

    /**
     * Compute the least upper bound of two initialization qualifiers. Returns null if one of the
     * qualifiers is not in the initialization hierarachy. Subclasses should override
     * leastUpperBound and call this method for initialization qualifiers.
     *
     * @param anno1 an initialization qualifier
     * @param qual1 a qualifier kind
     * @param anno2 an initialization qualifier
     * @param qual2 a qualifier kind
     * @return the lub of anno1 and anno2
     */
    protected AnnotationMirror leastUpperBoundInitialization(
        AnnotationMirror anno1, QualifierKind qual1, AnnotationMirror anno2, QualifierKind qual2) {
      if (!isInitializationAnnotation(anno1) || !isInitializationAnnotation(anno2)) {
        return null;
      }

      // Handle the case where one is a subtype of the other.
      if (isSubtypeInitialization(anno1, qual1, anno2, qual2)) {
        return anno2;
      } else if (isSubtypeInitialization(anno2, qual2, anno1, qual1)) {
        return anno1;
      }
      boolean unknowninit1 = isUnknownInitialization(anno1);
      boolean unknowninit2 = isUnknownInitialization(anno2);
      boolean underinit1 = isUnderInitialization(anno1);
      boolean underinit2 = isUnderInitialization(anno2);

      // Handle @Initialized.
      if (isInitialized(anno1)) {
        assert underinit2;
        return createUnknownInitializationAnnotation(getTypeFrameFromAnnotation(anno2));
      } else if (isInitialized(anno2)) {
        assert underinit1;
        return createUnknownInitializationAnnotation(getTypeFrameFromAnnotation(anno1));
      }

      if (underinit1 && underinit2) {
        return createUnderInitializationAnnotation(
            lubTypeFrame(getTypeFrameFromAnnotation(anno1), getTypeFrameFromAnnotation(anno2)));
      }

      assert (unknowninit1 || underinit1) && (unknowninit2 || underinit2);
      return createUnknownInitializationAnnotation(
          lubTypeFrame(getTypeFrameFromAnnotation(anno1), getTypeFrameFromAnnotation(anno2)));
    }

    /**
     * Returns the least upper bound of two types.
     *
     * @param a the first argument
     * @param b the second argument
     * @return the lub of the two arguments
     */
    protected TypeMirror lubTypeFrame(TypeMirror a, TypeMirror b) {
      if (types.isSubtype(a, b)) {
        return b;
      } else if (types.isSubtype(b, a)) {
        return a;
      }

      return TypesUtils.leastUpperBound(a, b, processingEnv);
    }

    /**
     * Compute the greatest lower bound of two initialization qualifiers. Returns null if one of the
     * qualifiers is not in the initialization hierarachy. Subclasses should override
     * greatestLowerBound and call this method for initialization qualifiers.
     *
     * @param anno1 an initialization qualifier
     * @param qual1 a qualifier kind
     * @param anno2 an initialization qualifier
     * @param qual2 a qualifier kind
     * @return the glb of anno1 and anno2
     */
    protected AnnotationMirror greatestLowerBoundInitialization(
        AnnotationMirror anno1, QualifierKind qual1, AnnotationMirror anno2, QualifierKind qual2) {
      if (!isInitializationAnnotation(anno1) || !isInitializationAnnotation(anno2)) {
        return null;
      }

      // Handle the case where one is a subtype of the other.
      if (isSubtypeInitialization(anno1, qual1, anno2, qual2)) {
        return anno1;
      } else if (isSubtypeInitialization(anno2, qual2, anno1, qual1)) {
        return anno2;
      }
      boolean unknowninit1 = isUnknownInitialization(anno1);
      boolean unknowninit2 = isUnknownInitialization(anno2);
      boolean underinit1 = isUnderInitialization(anno1);
      boolean underinit2 = isUnderInitialization(anno2);

      // Handle @Initialized.
      if (isInitialized(anno1)) {
        assert underinit2;
        return FBCBOTTOM;
      } else if (isInitialized(anno2)) {
        assert underinit1;
        return FBCBOTTOM;
      }

      TypeMirror typeFrame =
          TypesUtils.greatestLowerBound(
              getTypeFrameFromAnnotation(anno1), getTypeFrameFromAnnotation(anno2), processingEnv);
      if (typeFrame.getKind() == TypeKind.ERROR || typeFrame.getKind() == TypeKind.INTERSECTION) {
        return FBCBOTTOM;
      }

      if (underinit1 && underinit2) {
        return createUnderInitializationAnnotation(typeFrame);
      }

      assert (unknowninit1 || underinit1) && (unknowninit2 || underinit2);
      return createUnderInitializationAnnotation(typeFrame);
    }
  }
}
