/*
 * Copyright 2009 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.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.javac.JdtCompiler.AdditionalTypeProviderDelegate;
import com.google.gwt.dev.javac.JdtCompiler.UnitProcessor;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.EventType;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Interner;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * Manages a centralized cache for compiled units.
 */
public class CompilationStateBuilder {

  /**
   * An opaque class that lets you compile more units later.
   */
  public class CompileMoreLater {

    private final class UnitProcessorImpl implements UnitProcessor {

      /**
       * A callback after the JDT compiler has compiled a .java file and created a matching
       * CompilationUnitDeclaration. We take this opportunity to create a matching CompilationUnit.
       */
      @Override
      public void process(CompilationUnitBuilder builder, CompilationUnitDeclaration cud,
          List<ImportReference> cudOriginaImports,
          List<CompiledClass> compiledClasses) {
        Event event = SpeedTracerLogger.start(DevModeEventType.CSB_PROCESS);
        try {
          // Collect parameter method names event when the compilation unit has errors.

          List<JDeclaredType> types = ImmutableList.of();
          final Set<String> jsniDeps = Sets.newHashSet();
          final Map<String, Binding> jsniRefs = Maps.newHashMap();
          Map<MethodDeclaration, JsniMethod> jsniMethods = ImmutableMap.of();
          List<String> apiRefs = ImmutableList.of();
          MethodArgNamesLookup methodArgs = new MethodArgNamesLookup();

          if (!cud.compilationResult().hasErrors()) {
            // Only collect jsniMethods, etc if the compilation unit does not have errors.
            jsniMethods =
                JsniMethodCollector.collectJsniMethods(cud, builder.getSourceMapPath(),
                    builder.getSource(), JsRootScope.INSTANCE, DummyCorrelationFactory.INSTANCE);

            JSORestrictionsChecker.check(jsoState, cud);

            // JSNI check + collect dependencies.
            JsniReferenceResolver
                .resolve(cud, cudOriginaImports, jsniMethods, jsniRefs,
                    new JsniReferenceResolver.TypeResolver() {
                      @Override
                      public ReferenceBinding resolveType(String sourceOrBinaryName) {
                        ReferenceBinding resolveType = compiler.resolveType(sourceOrBinaryName);
                        if (resolveType != null) {
                          jsniDeps.add(String.valueOf(resolveType.qualifiedSourceName()));
                        }
                        return resolveType;
                      }
                    });

            // GWT drives JDT in a way that allows missing references in the source to be
            // resolved to precompiled bytecode on disk (see INameEnvironment). This is
            // done so that annotations can be supplied in bytecode form only. But since no
            // AST is available for these types it creates the danger that some functional
            // class (not just an annotation) gets filled in but is missing AST. This would
            // cause later compiler stages to fail.
            BinaryTypeReferenceRestrictionsChecker.check(cud);

            if (!cud.compilationResult().hasErrors()) {
              // The above checks might have recorded errors; so we need to check here again.
              // So only construct the GWT AST if no JDT errors and no errors from our checks.
              types = GwtAstBuilder.process(cud, builder.getSourceMapPath(), jsniMethods, jsniRefs,
                  compilerContext);
            }

            // Only run this pass if JDT was able to compile the unit with no errors, otherwise
            // the JDT AST traversal might throw exceptions.
            methodArgs = MethodParamCollector.collect(cud, builder.getSourceMapPath());
          }
          apiRefs = compiler.collectApiRefs(cud);

          final Interner<String> interner = StringInterner.get();
          String packageName = interner.intern(Shared.getPackageName(builder.getTypeName()));

          List<String> unresolvedSimple = Lists.newArrayList();
          for (char[] simpleRef : cud.compilationResult().simpleNameReferences) {
            unresolvedSimple.add(interner.intern(String.valueOf(simpleRef)));
          }

          List<String> unresolvedQualified = Lists.newArrayList();
          for (char[][] qualifiedRef : cud.compilationResult().qualifiedReferences) {
            unresolvedQualified.add(interner.intern(CharOperation.toString(qualifiedRef)));
          }
          for (String jsniDep : jsniDeps) {
            unresolvedQualified.add(interner.intern(jsniDep));
          }
          for (int i = 0; i < apiRefs.size(); ++i) {
            apiRefs.set(i, interner.intern(apiRefs.get(i)));
          }

          // Dependencies need to be included even when the {@code cud} has errors as the unit might
          // be saved as a cached unit and its dependencies might be used to further invalidate
          // other units. See {@link
          // CompilationStateBuilder#removeInvalidCachedUnitsAndRescheduleCorrespondingBuilders}.
          Dependencies dependencies =
              new Dependencies(packageName, unresolvedQualified, unresolvedSimple, apiRefs);

          for (CompiledClass cc : compiledClasses) {
            allValidClasses.put(cc.getSourceName(), cc);
          }

          // Even when compilation units have errors, return a consistent builder.
          builder
              .setTypes(types)
              .setDependencies(dependencies)
              .setJsniMethods(jsniMethods.values())
              .setMethodArgs(methodArgs)
              .setClasses(compiledClasses)
              .setProblems(cud.compilationResult().getProblems());

          buildQueue.add(builder);
        } finally {
          event.end();
        }
      }
    }

    /**
     * A global cache of all currently-valid class files keyed by source name.
     * This is used to validate dependencies when reusing previously cached
     * units, to make sure they can be recompiled if necessary.
     */
    private final Map<String, CompiledClass> allValidClasses = Maps.newHashMap();

    private transient LinkedBlockingQueue<CompilationUnitBuilder> buildQueue;

    /**
     * The JDT compiler.
     */
    private final JdtCompiler compiler;

    /**
     * Continuation state for JSNI checking.
     */
    private final JSORestrictionsChecker.CheckerState jsoState =
        new JSORestrictionsChecker.CheckerState();

    private final boolean suppressErrors;

    private CompilerContext compilerContext;

    public CompileMoreLater(
        CompilerContext compilerContext, AdditionalTypeProviderDelegate delegate) {
      this.compilerContext = compilerContext;
      this.compiler = new JdtCompiler(
          compilerContext, new UnitProcessorImpl());
      this.suppressErrors = !compilerContext.getOptions().isStrict();
      compiler.setAdditionalTypeProviderDelegate(delegate);
    }

    /**
     * Compiles generated source files (unless cached) and adds them to the
     * CompilationState. If the compiler aborts, logs an error and throws
     * UnableToCompleteException.
     */
    public Collection<CompilationUnit> addGeneratedTypes(TreeLogger logger,
        Collection<GeneratedUnit> generatedUnits, CompilationState compilationState)
        throws UnableToCompleteException {
      Event event = SpeedTracerLogger.start(DevModeEventType.CSB_ADD_GENERATED_TYPES);
      try {
        return doBuildGeneratedTypes(logger, compilerContext, generatedUnits, compilationState,
            this);
      } finally {
        event.end();
      }
    }

    public Map<String, CompiledClass> getValidClasses() {
      return Collections.unmodifiableMap(allValidClasses);
    }

    void addValidUnit(CompilationUnit unit) {
      compiler.addCompiledUnit(unit);
      for (CompiledClass cc : unit.getCompiledClasses()) {
        allValidClasses.put(cc.getSourceName(), cc);
      }
    }

    /**
     * Compiles the source code in each supplied CompilationUnitBuilder into a CompilationUnit and
     * reports errors.
     *
     * <p>A compilation unit is considered invalid if any of its dependencies (recursively) isn't
     * being compiled and isn't in allValidClasses, or if it has a signature that doesn't match
     * a dependency. Valid compilation units will be added to cachedUnits and the unit cache, and
     * their types will be added to allValidClasses. Invalid compilation units will be removed.</p>
     *
     * <p>I/O: serializes the AST of each Java type to DiskCache. (This happens even if the
     * compilation unit is later dropped.) If we're using the persistent unit cache, each valid
     * unit will also be serialized to the gwt-unitcache file. (As a result, each AST will be
     * copied there from the DiskCache.) A new persistent unit cache file will be created
     * each time compile() is called (if there's at least one valid unit) and the entire cache
     * will be rewritten to disk every {@link PersistentUnitCache#CACHE_FILE_THRESHOLD} files.</p>
     *
     * <p>This function won't report errors in invalid source files unless suppressErrors is false.
     * Instead, a summary giving the number of invalid files will be logged.</p>
     *
     * <p>If the JDT compiler aborts, logs an error and throws UnableToCompleteException. (This
     * doesn't happen for normal compile errors.)</p>
     */
    Collection<CompilationUnit> compile(TreeLogger logger, CompilerContext compilerContext,
        Collection<CompilationUnitBuilder> builders,
        Map<CompilationUnitBuilder, CompilationUnit> cachedUnits, EventType eventType)
        throws UnableToCompleteException {
      UnitCache unitCache = compilerContext.getUnitCache();
      // Initialize the set of valid classes to the initially cached units.
      for (CompilationUnit unit : cachedUnits.values()) {
        for (CompiledClass cc : unit.getCompiledClasses()) {
          // Map by source name.
          String sourceName = cc.getSourceName();
          allValidClasses.put(sourceName, cc);
        }
      }

      List<CompilationUnit> resultUnits = Lists.newArrayList();
      do {
        final TreeLogger branch = logger.branch(TreeLogger.TRACE, "Compiling...");
        // Compile anything that needs to be compiled.
        buildQueue = new LinkedBlockingQueue<CompilationUnitBuilder>();
        final List<CompilationUnit> newlyBuiltUnits = Lists.newArrayList();
        final CompilationUnitBuilder sentinel = CompilationUnitBuilder.create((GeneratedUnit) null);
        final Throwable[] workerException = new Throwable[1];
        final ProgressLogger progressLogger =
            new ProgressLogger(branch, TreeLogger.TRACE, builders.size(), 10);
        Thread buildThread = new Thread() {
          @Override
          public void run() {
            int processedCompilationUnitBuilders = 0;
            try {
              do {
                CompilationUnitBuilder builder = buildQueue.take();
                if (!progressLogger.isTimerStarted()) {
                  // Set start time here, after first job has arrived, since it can take a little
                  // while for the first job to arrive, and this helps with the accuracy of the
                  // estimated times.
                  progressLogger.startTimer();
                }
                if (builder == sentinel) {
                  return;
                }
                // Expensive, must serialize GWT AST types to bytes.
                CompilationUnit unit = builder.build();
                newlyBuiltUnits.add(unit);

                processedCompilationUnitBuilders++;
                progressLogger.updateProgress(processedCompilationUnitBuilders);
              } while (true);
            } catch (Throwable e) {
              workerException[0] = e;
            }
          }
        };
        buildThread.setName("CompilationUnitBuilder");
        buildThread.start();
        Event jdtCompilerEvent = SpeedTracerLogger.start(eventType);
        long compilationStartNanos = System.nanoTime();
        try {
          compiler.doCompile(branch, builders);
        } finally {
          jdtCompilerEvent.end();
        }
        buildQueue.add(sentinel);
        try {
          buildThread.join();
          long compilationNanos = System.nanoTime() - compilationStartNanos;
          // Convert nanos to seconds.
          double compilationSeconds = compilationNanos / (double) TimeUnit.SECONDS.toNanos(1);
          branch.log(TreeLogger.TRACE,
              String.format("Compilation completed in %.02f seconds", compilationSeconds));
          if (workerException[0] != null) {
            throw workerException[0];
          }
        } catch (RuntimeException e) {
          throw e;
        } catch (Throwable e) {
          throw new RuntimeException("Exception processing units", e);
        } finally {
          buildQueue = null;
        }
        resultUnits.addAll(newlyBuiltUnits);
        builders.clear();

        // Resolve all newly built unit deps against the global classes.
        for (CompilationUnit unit : newlyBuiltUnits) {
          unit.getDependencies().resolve(allValidClasses);
        }

        removeInvalidCachedUnitsAndRescheduleCorrespondingBuilders(logger, builders, cachedUnits);
      } while (builders.size() > 0);

      for (CompilationUnit unit : resultUnits) {
        unitCache.add(unit);
      }

      // Any remaining cached units are valid now.
      resultUnits.addAll(cachedUnits.values());

      // Done with a pass of the build - tell the cache its OK to cleanup
      // stale cache files.
      unitCache.cleanup(logger);

      // Report warnings.
      Type logLevelForWarnings = suppressErrors ? TreeLogger.DEBUG : TreeLogger.WARN;
      int warningCount =
          CompilationProblemReporter.logWarnings(logger, logLevelForWarnings, resultUnits);
      if (warningCount > 0 && !logger.isLoggable(logLevelForWarnings)) {
        logger.log(TreeLogger.INFO, "Ignored " + warningCount + " unit"
            + (warningCount > 1 ? "s" : "") + " with compilation errors in first pass.\n"
            + "Compile with -strict or with -logLevel set to DEBUG or WARN to see all errors.");
      }

      // Index errors so that error chains can be reported.
      CompilationProblemReporter.indexErrors(compilerContext.getCompilationErrorsIndex(),
          resultUnits);

      // Report error chains and hints.
      Type logLevelForErrors = suppressErrors ? TreeLogger.TRACE : TreeLogger.ERROR;
      int errorCount = CompilationProblemReporter.logErrorTrace(logger, logLevelForErrors,
          compilerContext, resultUnits, false);
      if (errorCount > 0 && !logger.isLoggable(logLevelForErrors)
          && logger.isLoggable(TreeLogger.INFO)) {
        logger.log(TreeLogger.INFO, "Ignored " + errorCount + " unit" + (errorCount > 1 ? "s" : "")
            + " with compilation errors in first pass.\n"
            + "Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.");
      }

      // Sort units to ensure stable output.
      Collections.sort(resultUnits, CompilationUnit.COMPARATOR);

      return resultUnits;
    }

    /**
     * Removes cached units that fail validation with the current set of valid classes; also
     * add the builder of the invalidated unit back for retry later.
     */
    private void removeInvalidCachedUnitsAndRescheduleCorrespondingBuilders(TreeLogger logger,
        Collection<CompilationUnitBuilder> builders,
        Map<CompilationUnitBuilder, CompilationUnit> cachedUnits) {

      /*
       * Invalidate any cached units with invalid refs.
       */
      Collection<CompilationUnit> invalidatedUnits = Lists.newArrayList();
      for (Iterator<Entry<CompilationUnitBuilder, CompilationUnit>> it =
          cachedUnits.entrySet().iterator(); it.hasNext();) {
        Entry<CompilationUnitBuilder, CompilationUnit> entry = it.next();
        CompilationUnit unit = entry.getValue();
        boolean isValid = unit.getDependencies().validate(logger, allValidClasses);
        if (isValid && unit.isError()) {
          // See if the unit has classes that can't provide a
          // NameEnvironmentAnswer
          for (CompiledClass cc : unit.getCompiledClasses()) {
            try {
              cc.getNameEnvironmentAnswer();
            } catch (ClassFormatException ex) {
              isValid = false;
              break;
            }
          }
        }
        if (!isValid) {
          if (logger.isLoggable(TreeLogger.TRACE)) {
            logger.log(TreeLogger.TRACE, "Invalid Unit: " + unit.getTypeName());
          }
          invalidatedUnits.add(unit);
          builders.add(entry.getKey());
          it.remove();
        }
      }

      if (invalidatedUnits.size() > 0) {
        if (logger.isLoggable(TreeLogger.TRACE)) {
          logger.log(TreeLogger.TRACE, "Invalid units found: " + invalidatedUnits.size());
        }
      }

      // Any units we invalidated must now be removed from the valid classes.
      for (CompilationUnit unit : invalidatedUnits) {
        for (CompiledClass cc : unit.getCompiledClasses()) {
          allValidClasses.remove(cc.getSourceName());
        }
      }
    }
  }

  private static final CompilationStateBuilder instance = new CompilationStateBuilder();

  /**
   * Compiles the given source files and adds them to the CompilationState. See
   * {@link CompileMoreLater#compile} for details.
   *
   * @throws UnableToCompleteException if the compiler aborts (not a normal compile error).
   */
  public static CompilationState buildFrom(
      TreeLogger logger, CompilerContext compilerContext, Set<Resource> resources)
      throws UnableToCompleteException {
    return buildFrom(logger, compilerContext, resources, null);
  }

  /**
   * Compiles the given source files and adds them to the CompilationState. See
   * {@link CompileMoreLater#compile} for details.
   *
   * @throws UnableToCompleteException if the compiler aborts (not a normal compile error).
   */
  public static CompilationState buildFrom(TreeLogger logger, CompilerContext compilerContext,
      Set<Resource> resources, AdditionalTypeProviderDelegate delegate)
      throws UnableToCompleteException {
    Event event = SpeedTracerLogger.start(DevModeEventType.CSB_BUILD_FROM_ORACLE);
    try {
      return instance.doBuildFrom(logger, compilerContext, resources, delegate);
    } finally {
      event.end();
    }
  }

  /**
   * Build a new compilation state from a source oracle. Allow the caller to
   * specify a compiler delegate that will handle undefined names.
   *
   * TODO: maybe use a finer brush than to synchronize the whole thing.
   */
  public synchronized CompilationState doBuildFrom(TreeLogger logger,
      CompilerContext compilerContext, Set<Resource> resources,
      AdditionalTypeProviderDelegate compilerDelegate)
    throws UnableToCompleteException {
    UnitCache unitCache = compilerContext.getUnitCache();
    assert unitCache != null : "CompilerContext should always contain a unit cache.";

    // Units we definitely want to build.
    List<CompilationUnitBuilder> builders = Lists.newArrayList();

    // Units we don't want to rebuild unless we have to.
    Map<CompilationUnitBuilder, CompilationUnit> cachedUnits = Maps.newIdentityHashMap();

    CompileMoreLater compileMoreLater = new CompileMoreLater(compilerContext, compilerDelegate);

    // For each incoming Java source file...
    for (Resource resource : resources) {
      // Create a builder for all incoming units.
      CompilationUnitBuilder builder = CompilationUnitBuilder.create(resource);

      CompilationUnit cachedUnit = unitCache.find(resource.getPathPrefix() + resource.getPath());

      if (cachedUnit != null && cachedUnit.getLastModified() == resource.getLastModified()) {
        // As verification is costly, this only runs the check when assertions are enabled.
        assert verifyContentId(logger, resource, cachedUnit);
      }

      // Try to rescue cached units from previous sessions where a jar has been
      // recompiled.
      if (cachedUnit != null && cachedUnit.getLastModified() != resource.getLastModified()) {
        unitCache.remove(cachedUnit);
        if (cachedUnit instanceof CachedCompilationUnit
            && cachedUnit.getContentId().equals(builder.getContentId())) {
          CachedCompilationUnit updatedUnit =
              new CachedCompilationUnit((CachedCompilationUnit) cachedUnit, resource
                  .getLastModified(), resource.getLocation());
          unitCache.add(updatedUnit);
        } else {
          cachedUnit = null;
        }
      }
      if (cachedUnit != null) {
        cachedUnits.put(builder, cachedUnit);
        compileMoreLater.addValidUnit(cachedUnit);
        continue;
      }
      builders.add(builder);
      compilerContext.getMinimalRebuildCache().addSourceCompilationUnitName(
          builder.getTypeName());
    }
    int cachedSourceCount = cachedUnits.size();
    int sourceCount = resources.size();
    if (logger.isLoggable(TreeLogger.TRACE)) {
      logger.log(TreeLogger.TRACE, "Found " + cachedSourceCount + " cached/archived units.  Used "
          + cachedSourceCount + " / " + sourceCount + " units from cache.");
    }

    Collection<CompilationUnit> resultUnits = compileMoreLater.compile(
        logger, compilerContext, builders, cachedUnits,
        CompilerEventType.JDT_COMPILER_CSB_FROM_ORACLE);

    TypeOracle typeOracle = new TypeOracle();
    CompilationUnitTypeOracleUpdater typeOracleUpdater =
        new CompilationUnitTypeOracleUpdater(typeOracle);

    CompilationState compilationState = new CompilationState(logger, compilerContext, typeOracle,
        typeOracleUpdater, resultUnits, compileMoreLater);
    compilationState.incrementStaticSourceCount(sourceCount);
    compilationState.incrementCachedStaticSourceCount(cachedSourceCount);
    return compilationState;
  }

  private boolean verifyContentId(TreeLogger logger, Resource resource, CompilationUnit cachedUnit) {
    if (!cachedUnit.getContentId().equals(getResourceContentId(resource))) {
      logger.log(TreeLogger.WARN, "Modification date hasn't changed but contentId has changed for "
          + resource.getLocation());
    }
    return true;
  }

  private ContentId getResourceContentId(Resource resource) {
    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
    try {
      InputStream in = resource.openContents();
      /**
       * In most cases openContents() will throw an exception, however in the case of a
       * ZipFileResource it might return null causing an NPE in Util.copyNoClose(), see issue 4359.
       */
      if (in == null) {
        throw new RuntimeException("Unexpected error reading resource '" + resource + "'");
      }
      // TODO: deprecate com.google.gwt.dev.util.Util and use Guava.
      Util.copy(in, out);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected error reading resource '" + resource + "'", e);
    }
    byte[] content = out.toByteArray();
    return new ContentId(Shared.getTypeName(resource), Util.computeStrongName(content));
  }

  public CompilationState doBuildFrom(
      TreeLogger logger, CompilerContext compilerContext, Set<Resource> resources)
      throws UnableToCompleteException {
    return doBuildFrom(logger, compilerContext, resources, null);
  }

  /**
   * Compile new generated units into an existing state.
   *
   * TODO: maybe use a finer brush than to synchronize the whole thing.
   */
  synchronized Collection<CompilationUnit> doBuildGeneratedTypes(TreeLogger logger,
      CompilerContext compilerContext, Collection<GeneratedUnit> generatedUnits,
      CompilationState compilationState, CompileMoreLater compileMoreLater)
      throws UnableToCompleteException {
    UnitCache unitCache = compilerContext.getUnitCache();

    // Units we definitely want to build.
    List<CompilationUnitBuilder> builders = Lists.newArrayList();
    // Units we don't want to rebuild unless we have to.
    Map<CompilationUnitBuilder, CompilationUnit> cachedUnits = Maps.newIdentityHashMap();

    // For each incoming generated Java source file...
    for (GeneratedUnit generatedUnit : generatedUnits) {
      // Create a builder for all incoming units.
      CompilationUnitBuilder builder = CompilationUnitBuilder.create(generatedUnit);

      // Look for units previously compiled
      CompilationUnit cachedUnit = unitCache.find(builder.getContentId());
      // Keep track of the names of units that are new or are known to have changed.
      if (cachedUnit != null) {
        // Recompile generated units with errors so source can be dumped.
        if (!cachedUnit.isError()) {
          cachedUnits.put(builder, cachedUnit);
          compileMoreLater.addValidUnit(cachedUnit);
          continue;
        }
      }
      builders.add(builder);
      compilerContext.getMinimalRebuildCache().addSourceCompilationUnitName(
          builder.getTypeName());
    }
    if (compilerContext.getOptions().isIncrementalCompileEnabled()) {
      compilerContext.getMinimalRebuildCache().recordGeneratedUnits(generatedUnits);
    }
    compilationState.incrementGeneratedSourceCount(builders.size() + cachedUnits.size());
    compilationState.incrementCachedGeneratedSourceCount(cachedUnits.size());
    return compileMoreLater.compile(logger, compilerContext, builders,
        cachedUnits, CompilerEventType.JDT_COMPILER_CSB_GENERATED);
  }
}
