package org.checkerframework.common.wholeprograminference;

import com.sun.source.tree.ClassTree;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.signature.qual.BinaryName;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.wholeprograminference.WholeProgramInference.OutputFormat;
import org.checkerframework.common.wholeprograminference.scenelib.ASceneWrapper;
import org.checkerframework.dataflow.analysis.Analysis;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.framework.qual.DefaultFor;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.DefaultQualifierInHierarchy;
import org.checkerframework.framework.qual.InvisibleQualifier;
import org.checkerframework.framework.qual.TypeUseLocation;
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.AnnotatedNullType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TypeAnnotationUtils;
import org.checkerframework.javacutil.UserError;
import scenelib.annotations.Annotation;
import scenelib.annotations.el.AClass;
import scenelib.annotations.el.AField;
import scenelib.annotations.el.AMethod;
import scenelib.annotations.el.AScene;
import scenelib.annotations.el.ATypeElement;
import scenelib.annotations.el.TypePathEntry;
import scenelib.annotations.io.IndexFileParser;
import scenelib.annotations.util.JVMNames;

/**
 * This class stores annotations using scenelib objects.
 *
 * <p>The set of annotations inferred for a certain class is stored in an {@link
 * scenelib.annotations.el.AScene}, which {@code writeScenes()} can write into a file. For example,
 * a class {@code my.pakkage.MyClass} will have its members' inferred types stored in a Scene, and
 * later written into a file named {@code my.pakkage.MyClass.jaif} if using {@link
 * OutputFormat#JAIF}, or {@code my.pakkage.MyClass.astub} if using {@link OutputFormat#STUB}.
 *
 * <p>This class populates the initial Scenes by reading existing .jaif files on the {@link
 * #JAIF_FILES_PATH} directory (regardless of output format). Having more information in those
 * initial .jaif files means that the precision achieved by the whole-program inference analysis
 * will be better. {@link #writeScenes} rewrites the initial .jaif files and may create new ones.
 */
public class WholeProgramInferenceScenesStorage
    implements WholeProgramInferenceStorage<ATypeElement> {

  /**
   * Directory where .jaif files will be written to and read from. This directory is relative to
   * where the CF's javac command is executed.
   */
  public static final String JAIF_FILES_PATH =
      "build" + File.separator + "whole-program-inference" + File.separator;

  /** The type factory associated with this WholeProgramInferenceScenesStorage. */
  protected final AnnotatedTypeFactory atypeFactory;

  /** Annotations that should not be output to a .jaif or stub file. */
  private final AnnotationsInContexts annosToIgnore = new AnnotationsInContexts();

  /**
   * If true, assignments where the rhs is null are be ignored.
   *
   * <p>If all assignments to a variable are null (because inference is being done with respect to a
   * limited set of uses) then the variable is inferred to have bottom type. That inference is
   * unlikely to be correct. To avoid that inference, set this variable to true. When the variable
   * is true, if all assignments are null, then none are recorded, no inference is done, and the
   * variable remains at its default type.
   */
  private final boolean ignoreNullAssignments;

  /** Maps .jaif file paths (Strings) to Scenes. Relative to JAIF_FILES_PATH. */
  public final Map<String, ASceneWrapper> scenes = new HashMap<>();

  /**
   * Scenes that were modified since the last time all Scenes were written into .jaif files. Each
   * String element of this set is a path (relative to JAIF_FILES_PATH) to the .jaif file of the
   * corresponding Scene in the set. It is obtained by passing a class name as argument to the
   * {@link #getJaifPath} method.
   *
   * <p>Modifying a Scene means adding (or changing) a type annotation for a field, method return
   * type, or method parameter type in the Scene. (Scenes are modified by the method {@link
   * #updateAnnotationSetInScene}.)
   */
  public final Set<String> modifiedScenes = new HashSet<>();

  /**
   * Default constructor.
   *
   * @param atypeFactory the type factory associated with this WholeProgramInferenceScenesStorage
   */
  public WholeProgramInferenceScenesStorage(AnnotatedTypeFactory atypeFactory) {
    this.atypeFactory = atypeFactory;
    boolean isNullness =
        atypeFactory.getClass().getSimpleName().equals("NullnessAnnotatedTypeFactory");
    this.ignoreNullAssignments = !isNullness;
  }

  @Override
  public String getFileForElement(Element elt) {
    String className;
    switch (elt.getKind()) {
      case CONSTRUCTOR:
      case METHOD:
        className = ElementUtils.getEnclosingClassName((ExecutableElement) elt);
        break;
      case LOCAL_VARIABLE:
        className = getEnclosingClassName((LocalVariableNode) elt);
        break;
      case FIELD:
        ClassSymbol enclosingClass = ((VarSymbol) elt).enclClass();
        className = enclosingClass.flatname.toString();
        break;
      default:
        throw new BugInCF("What element? %s %s", elt.getKind(), elt);
    }
    String file = getJaifPath(className);
    return file;
  }

  /**
   * Get the annotations for a class.
   *
   * @param className the name of the class, in binary form
   * @param file the path to the file that represents the class
   * @param classSymbol optionally, the ClassSymbol representing the class
   * @return the annotations for the class
   */
  private AClass getClassAnnos(
      @BinaryName String className, String file, @Nullable ClassSymbol classSymbol) {
    // Possibly reads .jaif file to obtain a Scene.
    ASceneWrapper scene = getScene(file);
    AClass aClass = scene.getAScene().classes.getVivify(className);
    scene.updateSymbolInformation(aClass, classSymbol);
    return aClass;
  }

  /**
   * Get the annotations for a method or constructor.
   *
   * @param methodElt the method or constructor
   * @return the annotations for a method or constructor
   */
  private AMethod getMethodAnnos(ExecutableElement methodElt) {
    String className = ElementUtils.getEnclosingClassName(methodElt);
    String file = getFileForElement(methodElt);
    AClass classAnnos = getClassAnnos(className, file, ((MethodSymbol) methodElt).enclClass());
    AMethod methodAnnos = classAnnos.methods.getVivify(JVMNames.getJVMMethodSignature(methodElt));
    methodAnnos.setFieldsFromMethodElement(methodElt);
    return methodAnnos;
  }

  @Override
  public boolean hasStorageLocationForMethod(ExecutableElement methodElt) {
    // The scenes implementation can always add annotations to a method.
    return true;
  }

  @Override
  public ATypeElement getParameterAnnotations(
      ExecutableElement methodElt,
      int i,
      AnnotatedTypeMirror paramATM,
      VariableElement ve,
      AnnotatedTypeFactory atypeFactory) {
    AMethod methodAnnos = getMethodAnnos(methodElt);
    AField param =
        methodAnnos.vivifyAndAddTypeMirrorToParameter(
            i, paramATM.getUnderlyingType(), ve.getSimpleName());
    return param.type;
  }

  @Override
  public ATypeElement getReceiverAnnotations(
      ExecutableElement methodElt,
      AnnotatedTypeMirror paramATM,
      AnnotatedTypeFactory atypeFactory) {
    AMethod methodAnnos = getMethodAnnos(methodElt);
    return methodAnnos.receiver.type;
  }

  @Override
  public ATypeElement getReturnAnnotations(
      ExecutableElement methodElt, AnnotatedTypeMirror atm, AnnotatedTypeFactory atypeFactory) {
    AMethod methodAnnos = getMethodAnnos(methodElt);
    return methodAnnos.returnType;
  }

  @Override
  public ATypeElement getFieldAnnotations(
      Element element,
      String fieldName,
      AnnotatedTypeMirror lhsATM,
      AnnotatedTypeFactory atypeFactory) {
    ClassSymbol enclosingClass = ((VarSymbol) element).enclClass();
    String file = getFileForElement(element);
    @SuppressWarnings("signature") // https://tinyurl.com/cfissue/3094
    @BinaryName String className = enclosingClass.flatname.toString();
    AClass classAnnos = getClassAnnos(className, file, enclosingClass);
    AField field = classAnnos.fields.getVivify(fieldName);
    field.setTypeMirror(lhsATM.getUnderlyingType());
    return field.type;
  }

  @Override
  public ATypeElement getPreOrPostconditionsForField(
      Analysis.BeforeOrAfter preOrPost,
      ExecutableElement methodElement,
      VariableElement fieldElement,
      AnnotatedTypeFactory atypeFactory) {
    switch (preOrPost) {
      case BEFORE:
        return getPreconditionsForField(methodElement, fieldElement, atypeFactory);
      case AFTER:
        return getPostconditionsForField(methodElement, fieldElement, atypeFactory);
      default:
        throw new BugInCF("Unexpected " + preOrPost);
    }
  }

  /**
   * Returns the precondition annotations for a field.
   *
   * @param methodElement the method
   * @param fieldElement the field
   * @param atypeFactory the type factory
   * @return the precondition annotations for a field
   */
  @SuppressWarnings("UnusedVariable")
  private ATypeElement getPreconditionsForField(
      ExecutableElement methodElement,
      VariableElement fieldElement,
      AnnotatedTypeFactory atypeFactory) {
    AMethod methodAnnos = getMethodAnnos(methodElement);
    TypeMirror typeMirror = TypeAnnotationUtils.unannotatedType(fieldElement.asType());
    return methodAnnos.vivifyAndAddTypeMirrorToPrecondition(fieldElement, typeMirror).type;
  }

  /**
   * Returns the postcondition annotations for a field.
   *
   * @param methodElement the method
   * @param fieldElement the field
   * @param atypeFactory the type factory
   * @return the postcondition annotations for a field
   */
  @SuppressWarnings("UnusedVariable")
  private ATypeElement getPostconditionsForField(
      ExecutableElement methodElement,
      VariableElement fieldElement,
      AnnotatedTypeFactory atypeFactory) {
    AMethod methodAnnos = getMethodAnnos(methodElement);
    TypeMirror typeMirror = TypeAnnotationUtils.unannotatedType(fieldElement.asType());
    return methodAnnos.vivifyAndAddTypeMirrorToPostcondition(fieldElement, typeMirror).type;
  }

  @Override
  public boolean addMethodDeclarationAnnotation(
      ExecutableElement methodElt, AnnotationMirror anno) {

    // Do not infer types for library code, only for type-checked source code.
    if (!ElementUtils.isElementFromSourceCode(methodElt)) {
      return false;
    }

    AMethod methodAnnos = getMethodAnnos(methodElt);

    scenelib.annotations.Annotation sceneAnno =
        AnnotationConverter.annotationMirrorToAnnotation(anno);
    boolean isNewAnnotation = methodAnnos.tlAnnotationsHere.add(sceneAnno);
    return isNewAnnotation;
  }

  /**
   * Write all modified scenes into files. (Scenes are modified by the method {@link
   * #updateAnnotationSetInScene}.)
   *
   * @param outputFormat the output format to use when writing files
   * @param checker the checker from which this method is called, for naming stub files
   */
  public void writeScenes(OutputFormat outputFormat, BaseTypeChecker checker) {
    // Create WPI directory if it doesn't exist already.
    File jaifDir = new File(JAIF_FILES_PATH);
    if (!jaifDir.exists()) {
      jaifDir.mkdirs();
    }
    // Write scenes into files.
    for (String jaifPath : modifiedScenes) {
      scenes.get(jaifPath).writeToFile(jaifPath, annosToIgnore, outputFormat, checker);
    }
    modifiedScenes.clear();
  }

  /**
   * Returns the String representing the .jaif path of a class given its name.
   *
   * @param className the simple name of a class
   * @return the path to the .jaif file
   */
  protected String getJaifPath(String className) {
    String jaifPath = JAIF_FILES_PATH + className + ".jaif";
    return jaifPath;
  }

  /**
   * Reads a Scene from the given .jaif file, or returns an empty Scene if the file does not exist.
   *
   * @param jaifPath the .jaif file
   * @return the Scene read from the file, or an empty Scene if the file does not exist
   */
  private ASceneWrapper getScene(String jaifPath) {
    AScene scene;
    if (!scenes.containsKey(jaifPath)) {
      File jaifFile = new File(jaifPath);
      scene = new AScene();
      if (jaifFile.exists()) {
        try {
          IndexFileParser.parseFile(jaifPath, scene);
        } catch (IOException e) {
          throw new UserError("Problem while reading %s: %s", jaifPath, e.getMessage());
        }
      }
      ASceneWrapper wrapper = new ASceneWrapper(scene);
      scenes.put(jaifPath, wrapper);
      return wrapper;
    } else {
      return scenes.get(jaifPath);
    }
  }

  /**
   * Returns the scene-lib representation of the given className in the scene identified by the
   * given jaifPath.
   *
   * @param className the name of the class to get, in binary form
   * @param jaifPath the path to the jaif file that would represent that class (must end in ".jaif")
   * @param classSymbol optionally, the ClassSymbol representing the class. Used to set the symbol
   *     information stored on an AClass.
   * @return a version of the scene-lib representation of the class, augmented with symbol
   *     information if {@code classSymbol} was non-null
   */
  protected AClass getAClass(
      @BinaryName String className, String jaifPath, @Nullable ClassSymbol classSymbol) {
    // Possibly reads .jaif file to obtain a Scene.
    ASceneWrapper scene = getScene(jaifPath);
    AClass aClass = scene.getAScene().classes.getVivify(className);
    scene.updateSymbolInformation(aClass, classSymbol);
    return aClass;
  }

  /**
   * Returns the scene-lib representation of the given className in the scene identified by the
   * given jaifPath.
   *
   * @param className the name of the class to get, in binary form
   * @param jaifPath the path to the jaif file that would represent that class (must end in ".jaif")
   * @return the scene-lib representation of the class, possibly augmented with symbol information
   *     if {@link #getAClass(String, String, com.sun.tools.javac.code.Symbol.ClassSymbol)} has
   *     already been called with a non-null third argument
   */
  protected AClass getAClass(@BinaryName String className, String jaifPath) {
    return getAClass(className, jaifPath, null);
  }

  /**
   * Updates the set of annotations in a location of a Scene, as the result of a pseudo-assignment.
   *
   * <ul>
   *   <li>If there was no previous annotation for that location, then the updated set will be the
   *       annotations in rhsATM.
   *   <li>If there was a previous annotation, the updated set will be the LUB between the previous
   *       annotation and rhsATM.
   * </ul>
   *
   * @param type ATypeElement of the Scene which will be modified
   * @param jaifPath path to a .jaif file for a Scene; used for marking the scene as modified
   *     (needing to be written to disk)
   * @param rhsATM the RHS of the annotated type on the source code
   * @param lhsATM the LHS of the annotated type on the source code
   * @param defLoc the location where the annotation will be added
   * @param ignoreIfAnnotated if true, don't update any type that is explicitly annotated in the
   *     source code
   */
  protected void updateAnnotationSetInScene(
      ATypeElement type,
      TypeUseLocation defLoc,
      AnnotatedTypeMirror rhsATM,
      AnnotatedTypeMirror lhsATM,
      String jaifPath,
      boolean ignoreIfAnnotated) {
    if (rhsATM instanceof AnnotatedNullType && ignoreNullAssignments) {
      return;
    }
    AnnotatedTypeMirror atmFromScene = atmFromStorageLocation(rhsATM.getUnderlyingType(), type);
    updateAtmWithLub(rhsATM, atmFromScene);
    if (lhsATM instanceof AnnotatedTypeVariable) {
      Set<AnnotationMirror> upperAnnos =
          ((AnnotatedTypeVariable) lhsATM).getUpperBound().getEffectiveAnnotations();
      // If the inferred type is a subtype of the upper bounds of the
      // current type on the source code, halt.
      if (upperAnnos.size() == rhsATM.getAnnotations().size()
          && atypeFactory.getQualifierHierarchy().isSubtype(rhsATM.getAnnotations(), upperAnnos)) {
        return;
      }
    }
    updateTypeElementFromATM(type, 1, defLoc, rhsATM, lhsATM, ignoreIfAnnotated);
    modifiedScenes.add(jaifPath);
  }

  /**
   * Updates sourceCodeATM to contain the LUB between sourceCodeATM and jaifATM, ignoring missing
   * AnnotationMirrors from jaifATM -- it considers the LUB between an AnnotationMirror am and a
   * missing AnnotationMirror to be am. The results are stored in sourceCodeATM.
   *
   * @param sourceCodeATM the annotated type on the source code
   * @param jaifATM the annotated type on the .jaif file
   */
  private void updateAtmWithLub(AnnotatedTypeMirror sourceCodeATM, AnnotatedTypeMirror jaifATM) {

    switch (sourceCodeATM.getKind()) {
      case TYPEVAR:
        updateAtmWithLub(
            ((AnnotatedTypeVariable) sourceCodeATM).getLowerBound(),
            ((AnnotatedTypeVariable) jaifATM).getLowerBound());
        updateAtmWithLub(
            ((AnnotatedTypeVariable) sourceCodeATM).getUpperBound(),
            ((AnnotatedTypeVariable) jaifATM).getUpperBound());
        break;
        //        case WILDCARD:
        // Because inferring type arguments is not supported, wildcards won't be encoutered
        //            updateAtmWithLub(((AnnotatedWildcardType)
        // sourceCodeATM).getExtendsBound(),
        //                              ((AnnotatedWildcardType)
        // jaifATM).getExtendsBound());
        //            updateAtmWithLub(((AnnotatedWildcardType)
        // sourceCodeATM).getSuperBound(),
        //                              ((AnnotatedWildcardType) jaifATM).getSuperBound());
        //            break;
      case ARRAY:
        updateAtmWithLub(
            ((AnnotatedArrayType) sourceCodeATM).getComponentType(),
            ((AnnotatedArrayType) jaifATM).getComponentType());
        break;
        // case DECLARED:
        // inferring annotations on type arguments is not supported, so no need to recur on
        // generic types. If this was every implemented, this method would need VisitHistory
        // object to prevent infinite recursion on types such as T extends List<T>.
      default:
        // ATM only has primary annotations
        break;
    }

    // LUB primary annotations
    Set<AnnotationMirror> annosToReplace = new HashSet<>(sourceCodeATM.getAnnotations().size());
    for (AnnotationMirror amSource : sourceCodeATM.getAnnotations()) {
      AnnotationMirror amJaif = jaifATM.getAnnotationInHierarchy(amSource);
      // amJaif only contains  annotations from the jaif, so it might be missing
      // an annotation in the hierarchy
      if (amJaif != null) {
        amSource = atypeFactory.getQualifierHierarchy().leastUpperBound(amSource, amJaif);
      }
      annosToReplace.add(amSource);
    }
    sourceCodeATM.replaceAnnotations(annosToReplace);
  }

  /**
   * Returns true if {@code am} should not be inserted in source code, for example {@link
   * org.checkerframework.common.value.qual.BottomVal}. This happens when {@code am} cannot be
   * inserted in source code or is the default for the location passed as argument.
   *
   * <p>Invisible qualifiers, which are annotations that contain the {@link
   * org.checkerframework.framework.qual.InvisibleQualifier} meta-annotation, also return true.
   *
   * <p>TODO: Merge functionality somewhere else with {@link
   * org.checkerframework.framework.util.defaults.QualifierDefaults}. Look into the
   * createQualifierDefaults method in {@link GenericAnnotatedTypeFactory} (which uses the
   * QualifierDefaults class linked above) before changing anything here. See
   * https://github.com/typetools/checker-framework/issues/683 .
   *
   * @param am an annotation to test for whether it should be inserted into source code
   * @param location where the location would be inserted; used to determine if {@code am} is the
   *     default for that location
   * @param atm its kind is used to determine if {@code am} is the default for that kind
   * @return true if am should not be inserted into source code, or if am is invisible
   */
  private boolean shouldIgnore(
      AnnotationMirror am, TypeUseLocation location, AnnotatedTypeMirror atm) {
    Element elt = am.getAnnotationType().asElement();
    // Checks if am is an implementation detail (a type qualifier used
    // internally by the type system and not meant to be seen by the user).
    Target target = elt.getAnnotation(Target.class);
    if (target != null && target.value().length == 0) {
      return true;
    }
    if (elt.getAnnotation(InvisibleQualifier.class) != null) {
      return true;
    }

    // Checks if am is default
    if (elt.getAnnotation(DefaultQualifierInHierarchy.class) != null) {
      return true;
    }
    DefaultQualifier defaultQual = elt.getAnnotation(DefaultQualifier.class);
    if (defaultQual != null) {
      for (TypeUseLocation loc : defaultQual.locations()) {
        if (loc == TypeUseLocation.ALL || loc == location) {
          return true;
        }
      }
    }
    DefaultFor defaultQualForLocation = elt.getAnnotation(DefaultFor.class);
    if (defaultQualForLocation != null) {
      for (TypeUseLocation loc : defaultQualForLocation.value()) {
        if (loc == TypeUseLocation.ALL || loc == location) {
          return true;
        }
      }
    }

    // Checks if am is a default annotation.
    // This case checks if it is meta-annotated with @DefaultFor.
    // TODO: Handle cases of annotations added via an
    // org.checkerframework.framework.type.treeannotator.LiteralTreeAnnotator.
    DefaultFor defaultFor = elt.getAnnotation(DefaultFor.class);
    if (defaultFor != null) {
      org.checkerframework.framework.qual.TypeKind[] types = defaultFor.typeKinds();
      TypeKind atmKind = atm.getUnderlyingType().getKind();
      if (hasMatchingTypeKind(atmKind, types)) {
        return true;
      }
    }

    return false;
  }

  /** Returns true, iff a matching TypeKind is found. */
  private boolean hasMatchingTypeKind(
      TypeKind atmKind, org.checkerframework.framework.qual.TypeKind[] types) {
    for (org.checkerframework.framework.qual.TypeKind tk : types) {
      if (tk.name().equals(atmKind.name())) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns a subset of annosSet, consisting of the annotations supported by the type factory
   * associated with this. These are not necessarily legal annotations: they have the right name,
   * but they may lack elements (fields).
   *
   * @param annosSet a set of annotations
   * @return the annoattions supported by this object's AnnotatedTypeFactory
   */
  private Set<Annotation> getSupportedAnnosInSet(Set<Annotation> annosSet) {
    Set<Annotation> output = new HashSet<>(1);
    Set<Class<? extends java.lang.annotation.Annotation>> supportedAnnos =
        atypeFactory.getSupportedTypeQualifiers();
    for (Annotation anno : annosSet) {
      for (Class<? extends java.lang.annotation.Annotation> clazz : supportedAnnos) {
        // TODO: Remove comparison by name, and make this routine more efficient.
        if (clazz.getName().equals(anno.def.name)) {
          output.add(anno);
        }
      }
    }
    return output;
  }

  @Override
  public AnnotatedTypeMirror atmFromStorageLocation(
      TypeMirror typeMirror, ATypeElement storageLocation) {
    AnnotatedTypeMirror result = AnnotatedTypeMirror.createType(typeMirror, atypeFactory, false);
    updateAtmFromATypeElement(result, storageLocation);
    return result;
  }

  /**
   * Updates an {@link org.checkerframework.framework.type.AnnotatedTypeMirror} to contain the
   * {@link scenelib.annotations.Annotation}s of an {@link scenelib.annotations.el.ATypeElement}.
   *
   * @param result the AnnotatedTypeMirror to be modified
   * @param storageLocation the {@link scenelib.annotations.el.ATypeElement} used
   */
  private void updateAtmFromATypeElement(AnnotatedTypeMirror result, ATypeElement storageLocation) {
    Set<Annotation> annos = getSupportedAnnosInSet(storageLocation.tlAnnotationsHere);
    for (Annotation anno : annos) {
      AnnotationMirror am =
          AnnotationConverter.annotationToAnnotationMirror(anno, atypeFactory.getProcessingEnv());
      result.addAnnotation(am);
    }
    if (result.getKind() == TypeKind.ARRAY) {
      AnnotatedArrayType aat = (AnnotatedArrayType) result;
      for (ATypeElement innerType : storageLocation.innerTypes.values()) {
        updateAtmFromATypeElement(aat.getComponentType(), innerType);
      }
    }
    if (result.getKind() == TypeKind.TYPEVAR) {
      AnnotatedTypeVariable atv = (AnnotatedTypeVariable) result;
      for (ATypeElement innerType : storageLocation.innerTypes.values()) {
        updateAtmFromATypeElement(atv.getUpperBound(), innerType);
      }
    }
  }

  @Override
  public void updateStorageLocationFromAtm(
      AnnotatedTypeMirror newATM,
      AnnotatedTypeMirror curATM,
      ATypeElement typeToUpdate,
      TypeUseLocation defLoc,
      boolean ignoreIfAnnotated) {
    updateTypeElementFromATM(typeToUpdate, 1, defLoc, newATM, curATM, ignoreIfAnnotated);
  }

  ///
  /// Writing to a file
  ///

  // The prepare*ForWriting hooks are needed in addition to the postProcessClassTree hook because
  // a scene may be modifed and written at any time, including before or after
  // postProcessClassTree is called.

  /**
   * Side-effects the compilation unit annotations to make any desired changes before writing to a
   * file.
   *
   * @param compilationUnitAnnos the compilation unit annotations to modify
   */
  public void prepareSceneForWriting(AScene compilationUnitAnnos) {
    for (Map.Entry<String, AClass> classEntry : compilationUnitAnnos.classes.entrySet()) {
      prepareClassForWriting(classEntry.getValue());
    }
  }

  /**
   * Side-effects the class annotations to make any desired changes before writing to a file.
   *
   * @param classAnnos the class annotations to modify
   */
  public void prepareClassForWriting(AClass classAnnos) {
    for (Map.Entry<String, AMethod> methodEntry : classAnnos.methods.entrySet()) {
      prepareMethodForWriting(methodEntry.getValue());
    }
  }

  /**
   * Side-effects the method or constructor annotations to make any desired changes before writing
   * to a file.
   *
   * @param methodAnnos the method or constructor annotations to modify
   */
  public void prepareMethodForWriting(AMethod methodAnnos) {
    atypeFactory.prepareMethodForWriting(methodAnnos);
  }

  @Override
  public void writeResultsToFile(
      WholeProgramInference.OutputFormat outputFormat, BaseTypeChecker checker) {
    if (outputFormat == OutputFormat.AJAVA) {
      throw new BugInCF("WholeProgramInferenceScenes used with format " + outputFormat);
    }

    for (String file : modifiedScenes) {
      ASceneWrapper scene = scenes.get(file);
      prepareSceneForWriting(scene.getAScene());
    }

    writeScenes(outputFormat, checker);
  }

  @Override
  public void setFileModified(String path) {
    modifiedScenes.add(path);
  }

  @Override
  public void preprocessClassTree(ClassTree classTree) {
    // This implementation does nothing.
  }

  /**
   * Updates an {@link scenelib.annotations.el.ATypeElement} to have the annotations of an {@link
   * org.checkerframework.framework.type.AnnotatedTypeMirror} passed as argument. Annotations in the
   * original set that should be ignored (see {@link #shouldIgnore}) are not added to the resulting
   * set. This method also checks if the AnnotatedTypeMirror has explicit annotations in source
   * code, and if that is the case no annotations are added for that location.
   *
   * <p>This method removes from the ATypeElement all annotations supported by this object's
   * AnnotatedTypeFactory before inserting new ones. It is assumed that every time this method is
   * called, the AnnotatedTypeMirror has a better type estimate for the ATypeElement. Therefore, it
   * is not a problem to remove all annotations before inserting the new annotations.
   *
   * @param typeToUpdate the ATypeElement that will be updated
   * @param idx used to write annotations on compound types of an ATypeElement
   * @param defLoc the location where the annotation will be added
   * @param newATM the AnnotatedTypeMirror whose annotations will be added to the ATypeElement
   * @param curATM used to check if the element which will be updated has explicit annotations in
   *     source code
   * @param ignoreIfAnnotated if true, don't update any type that is explicitly annotated in the
   *     source code
   */
  private void updateTypeElementFromATM(
      ATypeElement typeToUpdate,
      int idx,
      TypeUseLocation defLoc,
      AnnotatedTypeMirror newATM,
      AnnotatedTypeMirror curATM,
      boolean ignoreIfAnnotated) {
    // Clears only the annotations that are supported by the relevant AnnotatedTypeFactory.
    // The others stay intact.
    if (idx == 1) {
      // This if avoids clearing the annotations multiple times in cases
      // of type variables and compound types.
      Set<Annotation> annosToRemove = getSupportedAnnosInSet(typeToUpdate.tlAnnotationsHere);
      // This method may be called consecutive times for the same ATypeElement.  Each time it is
      // called, the AnnotatedTypeMirror has a better type estimate for the ATypeElement. Therefore,
      // it is not a problem to remove all annotations before inserting the new annotations.
      typeToUpdate.tlAnnotationsHere.removeAll(annosToRemove);
    }

    // Only update the ATypeElement if there are no explicit annotations.
    if (curATM.getExplicitAnnotations().isEmpty() || !ignoreIfAnnotated) {
      for (AnnotationMirror am : newATM.getAnnotations()) {
        addAnnotationsToATypeElement(
            newATM, typeToUpdate, defLoc, am, curATM.hasEffectiveAnnotation(am));
      }
    } else if (curATM.getKind() == TypeKind.TYPEVAR) {
      // getExplicitAnnotations will be non-empty for type vars whose bounds are explicitly
      // annotated.  So instead, only insert the annotation if there is not primary annotation
      // of the same hierarchy.  #shouldIgnore prevent annotations that are subtypes of type
      // vars upper bound from being inserted.
      for (AnnotationMirror am : newATM.getAnnotations()) {
        if (curATM.getAnnotationInHierarchy(am) != null) {
          // Don't insert if the type is already has a primary annotation
          // in the same hierarchy.
          break;
        }
        addAnnotationsToATypeElement(
            newATM, typeToUpdate, defLoc, am, curATM.hasEffectiveAnnotation(am));
      }
    }

    // Recursively update compound type and type variable type if they exist.
    if (newATM.getKind() == TypeKind.ARRAY && curATM.getKind() == TypeKind.ARRAY) {
      AnnotatedArrayType newAAT = (AnnotatedArrayType) newATM;
      AnnotatedArrayType oldAAT = (AnnotatedArrayType) curATM;
      updateTypeElementFromATM(
          typeToUpdate.innerTypes.getVivify(
              TypePathEntry.getTypePathEntryListFromBinary(Collections.nCopies(2 * idx, 0))),
          idx + 1,
          defLoc,
          newAAT.getComponentType(),
          oldAAT.getComponentType(),
          ignoreIfAnnotated);
    }
  }

  private void addAnnotationsToATypeElement(
      AnnotatedTypeMirror newATM,
      ATypeElement typeToUpdate,
      TypeUseLocation defLoc,
      AnnotationMirror am,
      boolean isEffectiveAnnotation) {
    Annotation anno = AnnotationConverter.annotationMirrorToAnnotation(am);
    typeToUpdate.tlAnnotationsHere.add(anno);
    if (isEffectiveAnnotation || shouldIgnore(am, defLoc, newATM)) {
      // firstKey works as a unique identifier for each annotation
      // that should not be inserted in source code
      String firstKey = aTypeElementToString(typeToUpdate);
      Pair<String, TypeUseLocation> key = Pair.of(firstKey, defLoc);
      Set<String> annosIgnored = annosToIgnore.get(key);
      if (annosIgnored == null) {
        annosIgnored = new HashSet<>();
        annosToIgnore.put(key, annosIgnored);
      }
      annosIgnored.add(anno.def().toString());
    }
  }

  /**
   * Returns a string representation of an ATypeElement, for use as part of a key in {@link
   * AnnotationsInContexts}.
   *
   * @param aType an ATypeElement to convert to a string representation
   * @return a string representation of the argument
   */
  public static String aTypeElementToString(ATypeElement aType) {
    // return aType.description.toString() + aType.tlAnnotationsHere;
    return aType.description.toString();
  }

  /**
   * Maps the {@link #aTypeElementToString} representation of an ATypeElement and its
   * TypeUseLocation to a set of names of annotations.
   */
  public static class AnnotationsInContexts
      extends HashMap<Pair<String, TypeUseLocation>, Set<String>> {
    private static final long serialVersionUID = 20200321L;
  }

  /**
   * Returns the "flatname" of the class enclosing {@code localVariableNode}.
   *
   * @param localVariableNode the {@link LocalVariableNode}
   * @return the "flatname" of the class enclosing {@code localVariableNode}
   */
  private static @BinaryName String getEnclosingClassName(LocalVariableNode localVariableNode) {
    return ElementUtils.getBinaryName(
        ElementUtils.enclosingTypeElement(localVariableNode.getElement()));
  }
}
