/*
 * Copyright 2014 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.StatementRanges;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.CompiledClass;
import com.google.gwt.dev.javac.GeneratedUnit;
import com.google.gwt.dev.javac.Shared;
import com.google.gwt.dev.jjs.JsSourceMap;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JTypeOracle;
import com.google.gwt.dev.jjs.ast.JTypeOracle.ImmediateTypeRelations;
import com.google.gwt.dev.jjs.impl.RapidTypeAnalyzer;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.IntTypeMapper;
import com.google.gwt.dev.js.JsIncrementalNamer.JsIncrementalNamerState;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.thirdparty.guava.common.base.Objects;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Multimaps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import cern.colt.list.IntArrayList;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * MinimalRebuildCache contains compiler information that can be persisted between compiles to
 * decrease compilation time.
 * <p>
 * Cached information is specific to a single permutation and it is the responsibility of the
 * framework driving the Compiler to supply the right Cache instance for the right Module
 * configuration and to make sure that the Compiler is only processing one permutation at a time.
 * <p>
 * All type names referenced here are assumed to be binary names.
 * <p>
 * A "typeName" here might be a root type or nested type but a "compilationUnitName" here will
 * always be the name of just the root type in a compilation unit.
 */
public class MinimalRebuildCache implements Serializable {

  private static void appendSubTypes(Set<String> accumulatedTypeNames, Set<String> parentTypeNames,
      JTypeOracle typeOracle) {
    for (String parentTypeName : parentTypeNames) {
      Iterables.addAll(accumulatedTypeNames, typeOracle.getSubTypeNames(parentTypeName));
    }
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private static void copyCollection(Collection fromCollection, Collection toCollection) {
    toCollection.clear();
    toCollection.addAll(fromCollection);
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private static void copyMap(Map fromMap, Map toMap) {
    toMap.clear();
    toMap.putAll(fromMap);
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private static void copyMultimap(Multimap fromMap, Multimap toMap) {
    toMap.clear();
    toMap.putAll(fromMap);
  }

  /**
   * Diffs lastModifiedByResourcePath from the previous compile against currentResources from the
   * current compile. modifiedResourcePaths is wiped and recreated to be a list of just the modified
   * or deleted resources, deletedResourcePaths is wiped and recreated to be a list of just the
   * deleted resources and modifiedResourcePaths is updated in place with new lastModified dates.
   */
  private static void recordModifiedResources(Map<String, Long> currentModifiedByResourcePath,
      Map<String, Long> lastModifiedByResourcePath, Set<String> modifiedResourcePaths,
      Set<String> deletedResourcePaths) {
    deletedResourcePaths.clear();
    modifiedResourcePaths.clear();

    Set<String> currentResourcePaths = Sets.newHashSet();
    for (Entry<String, Long> entry : currentModifiedByResourcePath.entrySet()) {
      String currentResourcePath = entry.getKey();
      Long currentResourceModified = entry.getValue();

      currentResourcePaths.add(currentResourcePath);
      Long lastKnownModified =
          lastModifiedByResourcePath.put(currentResourcePath, currentResourceModified);
      if (!Objects.equal(lastKnownModified, currentResourceModified)) {
        // Added or Modified resource.
        modifiedResourcePaths.add(currentResourcePath);
      }
    }

    // Removed resources.
    {
      // Figure out which resources were removed.
      Set<String> removedResourcePaths = Sets.newHashSet(
          Sets.difference(lastModifiedByResourcePath.keySet(), currentResourcePaths));
      // Log them as "modified".
      deletedResourcePaths.addAll(removedResourcePaths);
      modifiedResourcePaths.addAll(removedResourcePaths);
      // Remove any path to modified date entries for them.
      for (String removedResourcePath : removedResourcePaths) {
        lastModifiedByResourcePath.remove(removedResourcePath);
      }
    }
  }

  private static Set<String> resourcePathsToCompilationUnitNames(Set<String> resourcePaths) {
    Set<String> compilationUnitNames = Sets.newHashSet();
    for (String resourcePath : resourcePaths) {
      compilationUnitNames.add(Shared.toTypeName(resourcePath));
    }
    return compilationUnitNames;
  }

  private static Map<String, Long> resourcesToModifiedByPath(Collection<Resource> resources) {
    Map<String, Long> modifiedByPath = Maps.newHashMap();
    for (Resource resource : resources) {
      modifiedByPath.put(resource.getPath(), resource.getLastModified());
    }
    return modifiedByPath;
  }

  /*
   * Update copyFrom() whenever adding more fields.
   */
  protected final ImmediateTypeRelations immediateTypeRelations = new ImmediateTypeRelations();
  private final Map<String, String> compilationUnitTypeNameByNestedTypeName = Maps.newHashMap();
  private final Map<String, String> contentHashByGeneratedTypeName = Maps.newHashMap();
  private final Set<String> deletedCompilationUnitNames = Sets.newHashSet();
  private final Set<String> deletedDiskSourcePaths = Sets.newHashSet();
  private final Set<String> deletedResourcePaths = Sets.newHashSet();
  private final Set<String> dualJsoImplInterfaceNames = Sets.newHashSet();
  private final Map<String, String> descriptionByExportedGlobalNames = Maps.newHashMap();
  private final Multimap<String, String> exportedGlobalNamesByTypeName = HashMultimap.create();
  private final ArtifactSet generatedArtifacts = new ArtifactSet();
  private final Multimap<String, String> generatedCompilationUnitNamesByReboundTypeNames =
      HashMultimap.create();
  private final IntTypeMapper intTypeMapper = new IntTypeMapper();
  private final Map<String, String> jsByTypeName = Maps.newHashMap();
  private final JsIncrementalNamerState jsIncrementalNamerState = new JsIncrementalNamerState();
  private final Set<String> jsoStatusChangedTypeNames = Sets.newHashSet();
  private final Set<String> jsoTypeNames = Sets.newHashSet();
  private Integer lastLinkedJsBytes;
  private final Map<String, Long> lastModifiedByDiskSourcePath = Maps.newHashMap();
  private final Map<String, Long> lastModifiedByResourcePath = Maps.newHashMap();
  private final Set<String> lastReachableTypeNames = Sets.newHashSet();
  private final Set<String> modifiedCompilationUnitNames = Sets.newHashSet();
  private final Set<String> modifiedDiskSourcePaths = Sets.newHashSet();
  private final Set<String> modifiedResourcePaths = Sets.newHashSet();
  private final Multimap<String, String> nestedTypeNamesByUnitTypeName = HashMultimap.create();
  private final Set<String> preambleTypeNames = Sets.newHashSet();
  private transient ImmutableSet<String> processedStaleTypeNames = ImmutableSet.<String> of();
  private final Multimap<String, String> rebinderTypeNamesByReboundTypeName = HashMultimap.create();
  private final Multimap<String, String> reboundTypeNamesByGeneratedCompilationUnitNames =
      HashMultimap.create();
  private final Multimap<String, String> reboundTypeNamesByInputResource = HashMultimap.create();
  private final Multimap<String, String> referencedTypeNamesByTypeName = HashMultimap.create();
  private final Set<String> rootTypeNames = Sets.newHashSet();
  private final Set<String> singleJsoImplInterfaceNames = Sets.newHashSet();
  private final Set<String> sourceCompilationUnitNames = Sets.newHashSet();
  private final Map<String, JsSourceMap> sourceMapsByTypeName = Maps.newHashMap();
  private final Set<String> staleTypeNames = Sets.newHashSet();
  private final Map<String, StatementRanges> statementRangesByTypeName = Maps.newHashMap();
  private StringAnalyzableTypeEnvironment typeEnvironment = new StringAnalyzableTypeEnvironment();
  private final Multimap<String, String> typeNamesByReferencingTypeName = HashMultimap.create();

  public String addExportedGlobalName(
      String exportedGlobalName, String description, String inTypeName) {
    exportedGlobalNamesByTypeName.put(inTypeName, exportedGlobalName);
    return descriptionByExportedGlobalNames.put(exportedGlobalName, description);
  }

  /**
   * Accumulates generated artifacts so that they can be output on recompiles even if no generators
   * are run.
   */
  public void addGeneratedArtifacts(ArtifactSet generatedArtifacts) {
    this.generatedArtifacts.addAll(generatedArtifacts);
  }

  public void addModifiedCompilationUnitNames(TreeLogger logger,
      Set<String> modifiedCompilationUnitNames) {
    logger.log(TreeLogger.DEBUG, "adding to cached list of known modified compilation units "
        + modifiedCompilationUnitNames);
    this.modifiedCompilationUnitNames.addAll(modifiedCompilationUnitNames);
  }

  public void addSourceCompilationUnitName(String sourceCompilationUnitName) {
    // sourceCompilationUnitNames contains all compilation unit type names seen so far even
    // across recompiles. There is a need to know whether a unit is available in source form (
    // either compiled from source in this iteration or its AST available from cache) so that
    // we insert the correct type of reference when we see a BinaryTypeReference in the JDT
    // AST. {@see GwtAstBuilder}.
    // NOTE: DO NOT RESET OR CLEAR THIS SET.
    this.sourceCompilationUnitNames.add(sourceCompilationUnitName);
  }

  public void addTypeReference(String fromTypeName, String toTypeName) {
    referencedTypeNamesByTypeName.put(fromTypeName, toTypeName);
    typeNamesByReferencingTypeName.put(toTypeName, fromTypeName);
  }

  public void associateReboundTypeWithGeneratedCompilationUnitName(String reboundTypeName,
      String generatedCompilationUnitName) {
    reboundTypeNamesByGeneratedCompilationUnitNames.put(generatedCompilationUnitName,
        reboundTypeName);
  }

  /**
   * Record that a Generator that was ran as a result of a GWT.create(ReboundType.class) call read a
   * particular resource.
   */
  public void associateReboundTypeWithInputResource(String reboundTypeName,
      String inputResourcePath) {
    reboundTypeNamesByInputResource.put(inputResourcePath, reboundTypeName);
  }

  public void clearPerTypeJsCache() {
    rootTypeNames.clear();
    preambleTypeNames.clear();

    deletedResourcePaths.clear();
    modifiedResourcePaths.clear();

    deletedDiskSourcePaths.clear();
    modifiedDiskSourcePaths.clear();
    contentHashByGeneratedTypeName.clear();

    jsByTypeName.clear();
    referencedTypeNamesByTypeName.clear();
    sourceMapsByTypeName.clear();
    statementRangesByTypeName.clear();
    typeNamesByReferencingTypeName.clear();
  }

  public void clearRebinderTypeAssociations(String rebinderTypeName) {
    rebinderTypeNamesByReboundTypeName.values().remove(rebinderTypeName);
  }

  public void clearReboundTypeAssociations(String reboundTypeName) {
    reboundTypeNamesByInputResource.values().remove(reboundTypeName);
    reboundTypeNamesByGeneratedCompilationUnitNames.values().remove(reboundTypeName);
  }

  /**
   * Calculates the set of stale types and clears their cached Js, StatementRanges and SourceMaps.
   * <p>
   * The calculation of stale types starts with the list of known modified types and expands that
   * set using various patterns intended to find any types whose output JS would be affected by the
   * changes in the modified types. For example if the parent of class Foo was changed then the
   * castmaps in all children of Foo need to be recreated.
   * <p>
   * In some ways this process is similar to that performed by the CompilationUnitInvalidator but it
   * differs both in what type of cached objects are being cleared (JS versus CompilationUnits) and
   * in what invalidation rules must be applied. CompilationUnitInvalidator is concerned only with
   * changes in interface while the invalidation here must also look at JSO promotion/demotion and
   * cast references because of the peculiarities of output JS format.
   */
  public Set<String> computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle typeOracle) {
    if (!isPopulated()) {
      return Sets.newHashSet();
    }

    // Cache the ReboundTypeNames -> GeneratedCompilationUnitNames reverse map as it will be needed
    // several times.
    generatedCompilationUnitNamesByReboundTypeNames.clear();
    Multimaps.invertFrom(reboundTypeNamesByGeneratedCompilationUnitNames,
        generatedCompilationUnitNamesByReboundTypeNames);

    // Store stale type names in a persisted field so that tests can inspect behavior.
    staleTypeNames.clear();

    Set<String> modifiedTypeNames = computeModifiedTypeNames();

    // Accumulate the names of stale types resulting from some known type or resource modifications,
    // using various patterns (sub types, referencing types, etc).
    {
      staleTypeNames.addAll(modifiedTypeNames);
      appendSubTypes(staleTypeNames, modifiedTypeNames, typeOracle);
      // Marks stale any type that references either a modified type or any subtype of a modified
      // type. The references of subtypes can be done away with once we revamp Array castmap
      // generation.
      ImmutableList<String> modifiedTypeAndSubTypeNames = ImmutableList.copyOf(staleTypeNames);
      appendReferencingTypes(staleTypeNames, modifiedTypeAndSubTypeNames);
      appendReferencingTypes(staleTypeNames, jsoStatusChangedTypeNames);
      staleTypeNames.addAll(
          computeTypesThatRebindTypes(computeReboundTypesAffectedByModifiedResources()));
      appendTypesToRegenerateStaleGeneratedTypes(staleTypeNames);

      // Generator output is affected by types queried from the TypeOracle but changes in these
      // types are not being directly supported at this time since some of them are already handled
      // because they are referenced by the Generator output and since changes in subtype queries
      // probably make GWTRPC output incompatible with a server anyway (and thus already forces a
      // restart).

      staleTypeNames.removeAll(JProgram.SYNTHETIC_TYPE_NAMES);
    }

    /*
     * Filter for just those stale types that are actually reachable. Since if they're not reachable
     * we don't want to artificially traverse them and unnecessarily reveal dependency problems. And
     * if they have become reachable, since they're missing JS, they will already be fully traversed
     * when seen in Unify.
     */
    copyCollection(filterUnreachableTypeNames(staleTypeNames), staleTypeNames);

    // These log lines can be expensive.
    if (logger.isLoggable(TreeLogger.DEBUG)) {
      logger.log(TreeLogger.DEBUG, "known modified types = " + modifiedTypeNames);
      logger.log(TreeLogger.DEBUG, "known modified resources = " + modifiedResourcePaths);
      logger.log(TreeLogger.DEBUG,
          "clearing cached output for resulting stale types = " + staleTypeNames);
    }

    for (String staleTypeName : staleTypeNames) {
      clearCachedTypeOutput(staleTypeName);
    }

    return Sets.newHashSet(staleTypeNames);
  }

  /**
   * Computes and returns the set of names of deleted types.
   * <p>
   * Deleted types are all those types that are nested within compilation units that are known to
   * have been deleted.
   */
  public Set<String> computeDeletedTypeNames() {
    return computeNestedTypeNames(deletedCompilationUnitNames);
  }

  /**
   * Computes and returns the set of names of modified types.
   * <p>
   * Modified types are all those types that are nested within compilation units that are known to
   * have been modified.
   */
  public Set<String> computeModifiedTypeNames() {
    // Accumulate the names of types that are nested within known modified compilation units.
    return computeNestedTypeNames(modifiedCompilationUnitNames);
  }

  /**
   * Computes and returns the names of the set of types that are referenceable within the method
   * level control flow starting from the entry methods, immortal codegen types and exported
   * JsInterop methods.
   * <p>
   * Should only be called once per compile, so that the "lastReachableTypeNames" list accurately
   * reflects the reachable types of the immediately previous compile.
   */
  public Set<String> computeReachableTypeNames() {
    RapidTypeAnalyzer rapidTypeAnalyzer = new RapidTypeAnalyzer(typeEnvironment);

    // Artificially reach and traverse immortal codegen types since references to these may have
    // been synthesized in JS generation. These will not be pruned.
    for (String immortalCodegenTypeName : JProgram.IMMORTAL_CODEGEN_TYPES_SET) {
      int immortalCodegenTypeId = typeEnvironment.getTypeIdByName(immortalCodegenTypeName);
      rapidTypeAnalyzer.markTypeIdReachable(immortalCodegenTypeId);
      // Includes the clinit method.
      rapidTypeAnalyzer.markMemberMethodIdsReachable(immortalCodegenTypeId);
    }

    // Artificially reach @JsExport and @JsType methods. Since the enclosing types are
    // not being marked instantiated or reachable there's still a chance that they will be pruned
    // if no instantiations or static references are found.
    IntArrayList enclosingTypeIds = typeEnvironment.getEnclosingTypeIdsOfExportedMethods();
    for (int i = 0; i < enclosingTypeIds.size(); i++) {
      int enclosingTypeId = enclosingTypeIds.get(i);
      IntArrayList exportedMethodIds =
          typeEnvironment.getExportedMemberMethodIdsIn(enclosingTypeId);
      if (exportedMethodIds == null) {
        continue;
      }

      for (int j = 0; j < exportedMethodIds.size(); j++) {
        int exportedMethodId = exportedMethodIds.get(j);
        rapidTypeAnalyzer.markMethodIdReachable(exportedMethodId, false);
      }
    }

    // Artificially reach types with @JsExport'ed or @JsType'ed static fields or methods (including
    // Constructors). These types will not be pruned.
    IntArrayList typeIdsWithExportedStaticReferences =
        typeEnvironment.getTypeIdsWithExportedStaticReferences();
    for (int i = 0; i < typeIdsWithExportedStaticReferences.size(); i++) {
      int typeId = typeIdsWithExportedStaticReferences.get(i);
      rapidTypeAnalyzer.markTypeIdReachable(typeId);
      String typeName = typeEnvironment.getTypeNameById(typeId);
      int typeClinitMethodId = typeEnvironment.getMethodIdByName(typeName + "::$clinit()V");
      rapidTypeAnalyzer.markMethodIdReachable(typeClinitMethodId, false);
    }

    // Reach and traverse entry method types. This is just the EntryMethodHolder
    // class and its init() function. It will not be pruned. This is the conceptual "root" of the
    // application execution.
    IntArrayList entryMethodIds = typeEnvironment.getEntryMethodIds();
    for (int i = 0; i < entryMethodIds.size(); i++) {
      int entryMethodId = entryMethodIds.get(i);
      int typeId = typeEnvironment.getEnclosingTypeId(entryMethodId);
      rapidTypeAnalyzer.markTypeIdReachable(typeId);
      // Includes the clinit method.
      rapidTypeAnalyzer.markMemberMethodIdsReachable(typeId);
    }

    // Perform rapid type analysis.
    IntArrayList reachableTypeIds = rapidTypeAnalyzer.computeReachableTypeIds();

    // Translate ids back to strings and keep the results around for the next compile.
    Set<String> reachableTypeNames = Sets.newHashSet();
    for (int i = 0; i < reachableTypeIds.size(); i++) {
      int reachableTypeId = reachableTypeIds.get(i);
      reachableTypeNames.add(typeEnvironment.getTypeNameById(reachableTypeId));
    }

    copyCollection(reachableTypeNames, lastReachableTypeNames);
    return reachableTypeNames;
  }

  /**
   * Replaces the contents of this cache with the contents of the given cache.
   * <p>
   * This operation should be kept fast as it will be called once per compile. At the moment it
   * takes about 2.5% of the time in an incremental recompile. If wanting to recover this time in
   * the future consider parallelizing the copy or grouping the values from hash tables with similar
   * keys into a single data object and hashtable so that fewer references need to be replicated.
   */
  public void copyFrom(MinimalRebuildCache that) {
    this.lastLinkedJsBytes = that.lastLinkedJsBytes;

    this.intTypeMapper.copyFrom(that.intTypeMapper);
    this.jsIncrementalNamerState.copyFrom(that.jsIncrementalNamerState);
    this.immediateTypeRelations.copyFrom(that.immediateTypeRelations);
    this.typeEnvironment.copyFrom(that.typeEnvironment);

    copyMap(that.compilationUnitTypeNameByNestedTypeName,
        this.compilationUnitTypeNameByNestedTypeName);
    copyMap(that.contentHashByGeneratedTypeName, this.contentHashByGeneratedTypeName);
    copyMap(that.descriptionByExportedGlobalNames, this.descriptionByExportedGlobalNames);
    copyMap(that.jsByTypeName, this.jsByTypeName);
    copyMap(that.lastModifiedByDiskSourcePath, this.lastModifiedByDiskSourcePath);
    copyMap(that.lastModifiedByResourcePath, this.lastModifiedByResourcePath);
    copyMap(that.sourceMapsByTypeName, this.sourceMapsByTypeName);
    copyMap(that.statementRangesByTypeName, this.statementRangesByTypeName);

    copyMultimap(that.exportedGlobalNamesByTypeName, this.exportedGlobalNamesByTypeName);
    copyMultimap(that.generatedCompilationUnitNamesByReboundTypeNames,
        this.generatedCompilationUnitNamesByReboundTypeNames);
    copyMultimap(that.nestedTypeNamesByUnitTypeName, this.nestedTypeNamesByUnitTypeName);
    copyMultimap(that.rebinderTypeNamesByReboundTypeName, this.rebinderTypeNamesByReboundTypeName);
    copyMultimap(that.reboundTypeNamesByGeneratedCompilationUnitNames,
        this.reboundTypeNamesByGeneratedCompilationUnitNames);
    copyMultimap(that.reboundTypeNamesByInputResource, this.reboundTypeNamesByInputResource);
    copyMultimap(that.referencedTypeNamesByTypeName, this.referencedTypeNamesByTypeName);
    copyMultimap(that.typeNamesByReferencingTypeName, this.typeNamesByReferencingTypeName);

    copyCollection(that.deletedCompilationUnitNames, this.deletedCompilationUnitNames);
    copyCollection(that.deletedDiskSourcePaths, this.deletedDiskSourcePaths);
    copyCollection(that.deletedResourcePaths, this.deletedResourcePaths);
    copyCollection(that.dualJsoImplInterfaceNames, this.dualJsoImplInterfaceNames);
    copyCollection(that.generatedArtifacts, this.generatedArtifacts);
    copyCollection(that.jsoStatusChangedTypeNames, this.jsoStatusChangedTypeNames);
    copyCollection(that.jsoTypeNames, this.jsoTypeNames);
    copyCollection(that.lastReachableTypeNames, this.lastReachableTypeNames);
    copyCollection(that.modifiedCompilationUnitNames, this.modifiedCompilationUnitNames);
    copyCollection(that.modifiedDiskSourcePaths, this.modifiedDiskSourcePaths);
    copyCollection(that.modifiedResourcePaths, this.modifiedResourcePaths);
    copyCollection(that.preambleTypeNames, this.preambleTypeNames);
    copyCollection(that.rootTypeNames, this.rootTypeNames);
    copyCollection(that.singleJsoImplInterfaceNames, this.singleJsoImplInterfaceNames);
    copyCollection(that.sourceCompilationUnitNames, this.sourceCompilationUnitNames);
    copyCollection(that.staleTypeNames, this.staleTypeNames);
  }

  /**
   * Return the set of provided typeNames with unreachable types filtered out.
   */
  public Set<String> filterUnreachableTypeNames(Set<String> typeNames) {
    return Sets.newHashSet(Sets.filter(typeNames, Predicates.in(lastReachableTypeNames)));
  }

  public ArtifactSet getGeneratedArtifacts() {
    return generatedArtifacts;
  }

  public ImmediateTypeRelations getImmediateTypeRelations() {
    return immediateTypeRelations;
  }

  public String getJs(String typeName) {
    return jsByTypeName.get(typeName);
  }

  public int getLastLinkedJsBytes() {
    return lastLinkedJsBytes;
  }

  @VisibleForTesting
  public Set<String> getModifiedCompilationUnitNames() {
    return modifiedCompilationUnitNames;
  }

  public JsIncrementalNamerState getPersistentPrettyNamerState() {
    return jsIncrementalNamerState;
  }

  public Set<String> getPreambleTypeNames() {
    return preambleTypeNames;
  }

  /**
   * Returns the set of the names of types that were processed as stale. This list can be larger
   * than the calculated list of stale types for example when a new reference is created to a type
   * that had not been processed in a previous compile.
   */
  public Set<String> getProcessedStaleTypeNames() {
    return processedStaleTypeNames;
  }

  public JsSourceMap getSourceMap(String typeName) {
    return sourceMapsByTypeName.get(typeName);
  }

  @VisibleForTesting
  public Set<String> getStaleTypeNames() {
    return staleTypeNames;
  }

  public StatementRanges getStatementRanges(String typeName) {
    return statementRangesByTypeName.get(typeName);
  }

  public StringAnalyzableTypeEnvironment getTypeEnvironment() {
    return typeEnvironment;
  }

  public IntTypeMapper getTypeMapper() {
    return intTypeMapper;
  }

  public boolean hasJs(String typeName) {
    return jsByTypeName.containsKey(typeName);
  }

  public boolean hasPreambleTypeNames() {
    return !preambleTypeNames.isEmpty();
  }

  /**
   * Returns true if there is cached data to reuse in the next recompile.
   */
  public boolean isPopulated() {
    return !immediateTypeRelations.isEmpty();
  }

  public boolean isSourceCompilationUnit(String compilationUnitName) {
    return sourceCompilationUnitNames.contains(compilationUnitName);
  }

  public boolean knowsLastLinkedJsBytes() {
    return lastLinkedJsBytes != null;
  }

  @VisibleForTesting
  public void markSourceFileStale(String typeName) {
    lastModifiedByDiskSourcePath.remove(typeName);
  }

  /**
   * Records the resource paths and modification dates of build resources in the current compile and
   * builds a list of known modified resource paths by comparing the resource paths and modification
   * dates of build resources in the previous compile with those of the current compile.
   */
  public void recordBuildResources(ModuleDef module) {
    Map<String, Long> currentModifiedByResourcePath =
        resourcesToModifiedByPath(module.getBuildResourceOracle().getResources());
    recordModifiedResources(currentModifiedByResourcePath, lastModifiedByResourcePath,
        modifiedResourcePaths, deletedResourcePaths);
  }

  /**
   * Records the paths and modification dates of source resources in the current compile and builds
   * a list of known modified paths by comparing the paths and modification dates of source
   * resources in the previous compile with those of the current compile.
   */
  @VisibleForTesting
  public void recordDiskSourceResources(Map<String, Long> currentModifiedByDiskSourcePath) {
    recordModifiedResources(currentModifiedByDiskSourcePath, lastModifiedByDiskSourcePath,
        modifiedDiskSourcePaths, deletedDiskSourcePaths);

    deletedCompilationUnitNames.clear();
    deletedCompilationUnitNames.addAll(resourcePathsToCompilationUnitNames(deletedDiskSourcePaths));
    modifiedCompilationUnitNames.clear();
    modifiedCompilationUnitNames.addAll(
        resourcePathsToCompilationUnitNames(modifiedDiskSourcePaths));
  }

  /**
   * Records the paths and modification dates of source resources in the current compile and builds
   * a list of known modified paths by comparing the paths and modification dates of source
   * resources in the previous compile with those of the current compile.
   */
  public void recordDiskSourceResources(ModuleDef module) {
    Map<String, Long> currentModifiedByDiskSourcePath =
        resourcesToModifiedByPath(module.getSourceResourceOracle().getResources());
    recordDiskSourceResources(currentModifiedByDiskSourcePath);
  }

  /**
   * Records the paths and content ids of generated source resources in the current compile and
   * updates a list of known modified paths by comparing the paths and content ids of generated
   * source resources in the previous compile with those of the current compile.
   */
  public void recordGeneratedUnits(Collection<GeneratedUnit> generatedUnits) {
    // Not all Generators are run on each compile so it is not possible to compare previous and
    // current generated units to detect deletions. As a result only modifications are tracked.

    for (GeneratedUnit generatedUnit : generatedUnits) {
      String currentStrongHash = generatedUnit.getStrongHash();
      String lastKnownStrongHash =
          contentHashByGeneratedTypeName.put(generatedUnit.getTypeName(), currentStrongHash);
      if (!Objects.equal(lastKnownStrongHash, currentStrongHash)) {
        // Added or Modified resource.
        modifiedCompilationUnitNames.add(generatedUnit.getTypeName());
      }
    }
  }

  @VisibleForTesting
  public void recordNestedTypeName(String compilationUnitTypeName, String nestedTypeName) {
    nestedTypeNamesByUnitTypeName.put(compilationUnitTypeName, nestedTypeName);
    compilationUnitTypeNameByNestedTypeName.put(nestedTypeName, compilationUnitTypeName);
  }

  public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit) {
    // For the root type in the compilation unit the source name and binary name are the same.
    String compilationUnitTypeName = compilationUnit.getTypeName();

    nestedTypeNamesByUnitTypeName.removeAll(compilationUnitTypeName);
    for (CompiledClass compiledClass : compilationUnit.getCompiledClasses()) {
      String nestedTypeName = InternalName.toBinaryName(compiledClass.getInternalName());
      recordNestedTypeName(compilationUnitTypeName, nestedTypeName);
    }
  }

  /**
   * Records that rebinder type Foo contains a GWT.create(ReboundTypeBar.class) call.
   */
  public void recordRebinderTypeForReboundType(String reboundTypeName, String rebinderType) {
    rebinderTypeNamesByReboundTypeName.put(reboundTypeName, rebinderType);
  }

  public void removeExportedNames(String inTypeName) {
    Collection<String> exportedGlobalNamesForType =
        exportedGlobalNamesByTypeName.removeAll(inTypeName);
    descriptionByExportedGlobalNames.keySet().removeAll(exportedGlobalNamesForType);
  }

  public void removeReferencesFrom(String fromTypeName) {
    Collection<String> toTypeNames = referencedTypeNamesByTypeName.get(fromTypeName);
    for (String toTypeName : toTypeNames) {
      typeNamesByReferencingTypeName.remove(toTypeName, fromTypeName);
    }
    referencedTypeNamesByTypeName.removeAll(fromTypeName);
  }

  public void setEntryMethodNames(List<String> entryMethodNames) {
    typeEnvironment.setEntryMethodNames(entryMethodNames);
  }

  public void setJsForType(TreeLogger logger, String typeName, String typeJs) {
    logger.log(TreeLogger.SPAM, "caching JS for type " + typeName);
    jsByTypeName.put(typeName, typeJs);
  }

  /**
   * Records the names of JSO subtypes, single impl interfaces and dual impl interfaces as well as
   * keeps track of types that entered or left one of the lists in the most recent iteration.
   */
  public void setJsoTypeNames(Set<String> jsoTypeNames, Set<String> singleJsoImplInterfaceNames,
      Set<String> dualJsoImplInterfaceNames) {
    this.jsoStatusChangedTypeNames.clear();
    this.jsoStatusChangedTypeNames.addAll(
        Sets.symmetricDifference(this.jsoTypeNames, jsoTypeNames));
    this.jsoStatusChangedTypeNames.addAll(
        Sets.symmetricDifference(this.singleJsoImplInterfaceNames, singleJsoImplInterfaceNames));
    this.jsoStatusChangedTypeNames.addAll(
        Sets.symmetricDifference(this.dualJsoImplInterfaceNames, dualJsoImplInterfaceNames));

    this.jsoTypeNames.clear();
    this.jsoTypeNames.addAll(jsoTypeNames);
    this.singleJsoImplInterfaceNames.clear();
    this.singleJsoImplInterfaceNames.addAll(singleJsoImplInterfaceNames);
    this.dualJsoImplInterfaceNames.clear();
    this.dualJsoImplInterfaceNames.addAll(dualJsoImplInterfaceNames);
  }

  public void setLastLinkedJsBytes(int lastLinkedJsBytes) {
    this.lastLinkedJsBytes = lastLinkedJsBytes;
  }

  public void setPreambleTypeNames(TreeLogger logger, Set<String> preambleTypeNames) {
    logger.log(TreeLogger.DEBUG, "caching list of known preamble types " + preambleTypeNames);
    this.preambleTypeNames.addAll(preambleTypeNames);
  }

  public void setProcessedStaleTypeNames(Set<String> processedStaleTypeNames) {
    // If this is the first compile.
    if (!isPopulated()) {
      // Don't record processed stale types, since the list is huge and not useful for test
      // assertions.
      return;
    }

    this.processedStaleTypeNames = ImmutableSet.copyOf(processedStaleTypeNames);
  }

  public void setRootTypeNames(Collection<String> rootTypeNames) {
    this.rootTypeNames.clear();
    this.rootTypeNames.addAll(rootTypeNames);
  }

  public void setSourceMapForType(String typeName, JsSourceMap sourceMap) {
    sourceMapsByTypeName.put(typeName, sourceMap);
  }

  public void setStatementRangesForType(String typeName, StatementRanges statementRanges) {
    statementRangesByTypeName.put(typeName, statementRanges);
  }

  @VisibleForTesting
  boolean hasSameContent(MinimalRebuildCache that) {
    // Ignoring processedStaleTypeNames since it is transient.
    return this.immediateTypeRelations.hasSameContent(that.immediateTypeRelations) && Objects.equal(
        this.compilationUnitTypeNameByNestedTypeName, that.compilationUnitTypeNameByNestedTypeName)
        && Objects.equal(this.contentHashByGeneratedTypeName, that.contentHashByGeneratedTypeName)
        && Objects.equal(this.deletedCompilationUnitNames, that.deletedCompilationUnitNames)
        && Objects.equal(this.deletedDiskSourcePaths, that.deletedDiskSourcePaths)
        && Objects.equal(this.deletedResourcePaths, that.deletedResourcePaths)
        && Objects.equal(this.dualJsoImplInterfaceNames, that.dualJsoImplInterfaceNames)
        && Objects.equal(this.generatedArtifacts, that.generatedArtifacts)
        && Objects.equal(this.descriptionByExportedGlobalNames,
            that.descriptionByExportedGlobalNames)
        && Objects.equal(this.exportedGlobalNamesByTypeName, that.exportedGlobalNamesByTypeName)
        && Objects.equal(this.generatedCompilationUnitNamesByReboundTypeNames,
            that.generatedCompilationUnitNamesByReboundTypeNames)
        && this.intTypeMapper.hasSameContent(that.intTypeMapper)
        && Objects.equal(this.jsByTypeName, that.jsByTypeName)
        && Objects.equal(this.jsoStatusChangedTypeNames, that.jsoStatusChangedTypeNames)
        && Objects.equal(this.jsoTypeNames, that.jsoTypeNames)
        && Objects.equal(this.lastLinkedJsBytes, that.lastLinkedJsBytes)
        && Objects.equal(this.lastModifiedByDiskSourcePath, that.lastModifiedByDiskSourcePath)
        && Objects.equal(this.lastModifiedByResourcePath, that.lastModifiedByResourcePath)
        && Objects.equal(this.lastReachableTypeNames, that.lastReachableTypeNames)
        && Objects.equal(this.modifiedCompilationUnitNames, that.modifiedCompilationUnitNames)
        && Objects.equal(this.modifiedDiskSourcePaths, that.modifiedDiskSourcePaths)
        && Objects.equal(this.modifiedResourcePaths, that.modifiedResourcePaths)
        && Objects.equal(this.nestedTypeNamesByUnitTypeName, that.nestedTypeNamesByUnitTypeName)
        && this.jsIncrementalNamerState.hasSameContent(that.jsIncrementalNamerState)
        && Objects.equal(this.preambleTypeNames, that.preambleTypeNames) && Objects.equal(
            this.rebinderTypeNamesByReboundTypeName, that.rebinderTypeNamesByReboundTypeName)
        && Objects.equal(this.reboundTypeNamesByGeneratedCompilationUnitNames,
            that.reboundTypeNamesByGeneratedCompilationUnitNames)
        && Objects.equal(this.reboundTypeNamesByInputResource, that.reboundTypeNamesByInputResource)
        && Objects.equal(this.referencedTypeNamesByTypeName, that.referencedTypeNamesByTypeName)
        && Objects.equal(this.rootTypeNames, that.rootTypeNames)
        && Objects.equal(this.singleJsoImplInterfaceNames, that.singleJsoImplInterfaceNames)
        && Objects.equal(this.sourceCompilationUnitNames, that.sourceCompilationUnitNames)
        && Objects.equal(this.sourceMapsByTypeName, that.sourceMapsByTypeName)
        && Objects.equal(this.staleTypeNames, that.staleTypeNames)
        && Objects.equal(this.statementRangesByTypeName, that.statementRangesByTypeName)
        && this.typeEnvironment.hasSameContent(that.typeEnvironment)
        && Objects.equal(this.typeNamesByReferencingTypeName, that.typeNamesByReferencingTypeName);
  }

  private void appendReferencingTypes(Set<String> accumulatedTypeNames,
      Collection<String> referencedTypeNames) {
    for (String referencedTypeName : referencedTypeNames) {
      Collection<String> referencingTypeNames =
          typeNamesByReferencingTypeName.get(referencedTypeName);
      accumulatedTypeNames.addAll(referencingTypeNames);
    }
  }

  /**
   * If type Foo is a generated type and is stale this pass will append type Bar that triggers
   * Generator Baz that regenerates type Foo.
   * <p>
   * This is necessary since just clearing the cache for type Foo would not be adequate to cause the
   * recreation of its cached JS without also rerunning the Generator that creates type Foo.
   */
  private void appendTypesToRegenerateStaleGeneratedTypes(Set<String> staleTypeNames) {
    Set<String> generatedCompilationUnitNames =
        reboundTypeNamesByGeneratedCompilationUnitNames.keySet();

    // Filter the current stale types list for any compilation units that are known to be generated.
    Set<String> staleGeneratedCompilationUnitNames = Sets.intersection(
        computeCompilationUnitNames(staleTypeNames), generatedCompilationUnitNames);
    boolean discoveredMoreStaleTypes;
    do {
      // Accumulate staleGeneratedCompilationUnits -> generators ->
      // generatorTriggeringCompilationUnits.
      Set<String> reboundTypesThatGenerateTheStaleCompilationUnits =
          computeReboundTypesThatGenerateTypes(staleGeneratedCompilationUnitNames);
      Set<String> generatorTriggeringTypes =
          computeTypesThatRebindTypes(reboundTypesThatGenerateTheStaleCompilationUnits);
      // Mark these generator triggering types stale and keep track of whether any of them were not
      // previously known to be stale.
      discoveredMoreStaleTypes = staleTypeNames.addAll(generatorTriggeringTypes);

      // It's possible that a generator triggering type was itself also created by a Generator.
      // Repeat the backwards trace process till none of the newly stale types are generated types.
      staleGeneratedCompilationUnitNames = Sets.intersection(
          computeCompilationUnitNames(generatorTriggeringTypes), generatedCompilationUnitNames);
    } while (discoveredMoreStaleTypes);
  }

  private void clearCachedTypeOutput(String staleTypeName) {
    jsByTypeName.remove(staleTypeName);
    statementRangesByTypeName.remove(staleTypeName);
    sourceMapsByTypeName.remove(staleTypeName);
  }

  /**
   * Returns the set of names of CompilationUnits that contain all of the given type names.
   */
  private Set<String> computeCompilationUnitNames(Set<String> typeNames) {
    Set<String> compilationUnitNames = Sets.newHashSet();
    for (String typeName : typeNames) {
      compilationUnitNames.add(compilationUnitTypeNameByNestedTypeName.get(typeName));
    }
    return compilationUnitNames;
  }

  /**
   * Returns the set of type names contained within the given compilation units.
   */
  private Set<String> computeNestedTypeNames(Set<String> compilationUnitNames) {
    Set<String> nestedTypeNames = Sets.newHashSet();
    nestedTypeNames.addAll(compilationUnitNames);
    for (String compilationUnitName : compilationUnitNames) {
      nestedTypeNames.addAll(nestedTypeNamesByUnitTypeName.get(compilationUnitName));
    }
    return nestedTypeNames;
  }

  /**
   * Returns the set of names of types that when rebound trigger Generators that access resources
   * which are known to have been modified.
   */
  private Set<String> computeReboundTypesAffectedByModifiedResources() {
    Set<String> affectedRebindTypeNames = Sets.newHashSet();
    for (String modifiedResourcePath : modifiedResourcePaths) {
      affectedRebindTypeNames.addAll(reboundTypeNamesByInputResource.get(modifiedResourcePath));
    }
    return affectedRebindTypeNames;
  }

  private Set<String> computeReboundTypesThatGenerateTypes(
      Set<String> staleGeneratedCompilationUnitNames) {
    Set<String> reboundTypesThatGenerateTypes = Sets.newHashSet();
    for (String staleGeneratedCompilationUnitName : staleGeneratedCompilationUnitNames) {
      reboundTypesThatGenerateTypes.addAll(
          reboundTypeNamesByGeneratedCompilationUnitNames.get(staleGeneratedCompilationUnitName));
    }
    return reboundTypesThatGenerateTypes;
  }

  /**
   * Returns the set of names of types that contain GWT.create(ReboundType.class) calls that rebind
   * the given set of type names.
   */
  private Set<String> computeTypesThatRebindTypes(Set<String> reboundTypeNames) {
    Set<String> typesThatRebindTypes = Sets.newHashSet();
    for (String reboundTypeName : reboundTypeNames) {
      typesThatRebindTypes.addAll(rebinderTypeNamesByReboundTypeName.get(reboundTypeName));
    }
    return typesThatRebindTypes;
  }
}
