/*
 * Copyright 2008 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.UnableToCompleteException;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.jdt.TypeRefVisitor;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.collect.ArrayListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.ListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.io.BaseEncoding;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Manages the process of compiling {@link CompilationUnit}s.
 */
public class JdtCompiler {
  /**
   * Provides hooks for changing the behavior of the JdtCompiler when unknown
   * types are encountered during compilation. Currently used for allowing
   * external tools to provide source lazily when undefined references appear.
   */
  public interface AdditionalTypeProviderDelegate {
    /**
     * Checks for additional packages which may contain additional compilation
     * units.
     *
     * @param slashedPackageName the '/' separated name of the package to find
     * @return <code>true</code> if such a package exists
     */
    boolean doFindAdditionalPackage(String slashedPackageName);

    /**
     * Finds a new compilation unit on-the-fly for the requested type, if there
     * is an alternate mechanism for doing so.
     *
     * @param binaryName the binary name of the requested type
     * @return a unit answering the name, or <code>null</code> if no such unit
     *         can be created
     */
    GeneratedUnit doFindAdditionalType(String binaryName);
  }

  /**
   * A default processor that simply collects build units.
   */
  public static final class DefaultUnitProcessor implements UnitProcessor {
    private final List<CompilationUnit> results = new ArrayList<CompilationUnit>();

    public DefaultUnitProcessor() {
    }

    public List<CompilationUnit> getResults() {
      return Lists.normalizeUnmodifiable(results);
    }

    @Override
    public void process(CompilationUnitBuilder builder, CompilationUnitDeclaration cud,
        List<ImportReference> cudOriginaImports, List<CompiledClass> compiledClasses) {
      builder.setClasses(compiledClasses).setTypes(Collections.<JDeclaredType> emptyList())
          .setDependencies(new Dependencies()).setJsniMethods(Collections.<JsniMethod> emptyList())
          .setMethodArgs(new MethodArgNamesLookup())
          .setProblems(cud.compilationResult().getProblems());
      results.add(builder.build());
    }
  }
  /**
   * Static cache of all the JRE package names.
   */
  public static class JreIndex {
    private static Set<String> packages = readPackages();

    public static boolean contains(String name) {
      return packages.contains(name);
    }

    private static void addPackageRecursively(Set<String> packages, String pkg) {
      if (!packages.add(pkg)) {
        return;
      }

      int i = pkg.lastIndexOf('/');
      if (i != -1) {
        addPackageRecursively(packages, pkg.substring(0, i));
      }
    }

    private static Set<String> readPackages() {
      HashSet<String> pkgs = new HashSet<String>();
      String klass = "java/lang/Object.class";
      URL url = ClassLoader.getSystemClassLoader().getResource(klass);
      try {
        JarURLConnection connection = (JarURLConnection) url.openConnection();
        JarFile f = connection.getJarFile();
        Enumeration<JarEntry> entries = f.entries();
        while (entries.hasMoreElements()) {
          JarEntry e = entries.nextElement();
          String name = e.getName();
          if (name.endsWith(".class")) {
            String pkg = Shared.getSlashedPackageFrom(name);
            addPackageRecursively(pkgs, pkg);
          }
        }
        return pkgs;
      } catch (IOException e) {
        throw new InternalCompilerException("Unable to find JRE", e);
      }
    }
  }

  /**
   * Interface for processing units on the fly during compilation.
   */
  public interface UnitProcessor {
    void process(CompilationUnitBuilder builder, CompilationUnitDeclaration cud,
        List<ImportReference> cudOriginalImports, List<CompiledClass> compiledClasses);
  }

  /**
   * Adapts a {@link CompilationUnit} for a JDT compile.
   */
  private static class Adapter implements ICompilationUnit {

    private final CompilationUnitBuilder builder;

    public Adapter(CompilationUnitBuilder builder) {
      this.builder = builder;
    }

    public CompilationUnitBuilder getBuilder() {
      return builder;
    }

    @Override
    public char[] getContents() {
      return builder.getSource().toCharArray();
    }

    @Override
    public char[] getFileName() {
      return builder.getLocation().toCharArray();
    }

    @Override
    public char[] getMainTypeName() {
      return Shared.getShortName(builder.getTypeName()).toCharArray();
    }

    @Override
    public char[][] getPackageName() {
      String packageName = Shared.getPackageName(builder.getTypeName());
      return CharOperation.splitOn('.', packageName.toCharArray());
    }

    @Override
    public boolean ignoreOptionalProblems() {
      return false;
    }

    @Override
    public String toString() {
      return builder.toString();
    }
  }

  /**
   * ParserImpl intercepts parsing of the source to get rid of methods, fields and classes
   * annotated with a *.GwtIncompatible annotation.
   */
  private static class ParserImpl extends Parser {

    // A place to stash imports before removal. These are needed to correctly check the
    // references in Jsni.
    // TODO(rluble): find a more modular way for this fix.
    public final ListMultimap<CompilationUnitDeclaration, ImportReference> originalImportsByCud =
        ArrayListMultimap.create();
    public ParserImpl(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
      super(problemReporter, optimizeStringLiterals);
    }

    /**
     * Overrides the main parsing entry point to filter out elements annotated with
     * {@code GwtIncompatible}.
     */
    @Override
    public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit,
        CompilationResult compilationResult) {
      // Never dietParse(), otherwise GwtIncompatible annotations in anonymoous inner classes
      // would be ignored.
      boolean saveDiet = this.diet;
      this.diet = false;
      CompilationUnitDeclaration decl = super.parse(sourceUnit, compilationResult);
      this.diet = saveDiet;
      // Remove @GwtIncompatible classes and members.
      // It is safe to remove @GwtIncompatible types, fields and methods on incomplete ASTs due
      // to parsing errors.
      GwtIncompatiblePreprocessor.preproccess(decl);
      if (decl.imports != null) {
        originalImportsByCud.putAll(decl, Arrays.asList(decl.imports));
      }
      if (decl.hasErrors()) {
        // The unit has parsing errors; its JDT AST might not be complete. In this case do not
        // remove unused imports as it is not safe to do so. UnusedImportsRemover would remove
        // imports for types only referred from parts of the AST that was not constructed.
        // Later the error reporting logic would complain about missing types for these references
        // potentially burying the real error among many spurious errors.
        return decl;
      }
      if (removeUnusedImports) {
        // Lastly remove any unused imports
        UnusedImportsRemover.exec(decl);
      }
      return decl;
    }
  }

  /**
   * Maximum number of JDT compiler errors or abort requests before it actually returns
   * a fatal error to the user.
   */
  private static final double ABORT_COUNT_MAX = 100;

  private class CompilerImpl extends Compiler {
    private TreeLogger logger;
    private int abortCount = 0;

    public CompilerImpl(TreeLogger logger, CompilerOptions compilerOptions) {
      super(new INameEnvironmentImpl(), DefaultErrorHandlingPolicies.proceedWithAllProblems(),
          compilerOptions, new ICompilerRequestorImpl(), new DefaultProblemFactory(
              Locale.getDefault()));
      this.logger = logger;
    }

    /**
     * Make the JDT compiler throw the exception so that it can be caught in {@link #doCompile}.
     */
    @Override
    protected void handleInternalException(AbortCompilation abortException,
        CompilationUnitDeclaration unit) {
      // Context: The JDT compiler doesn't rethrow AbortCompilation in Compiler.compile().
      // Instead it just exits early with a random selection of compilation units never getting
      // compiled. This makes sense when an Eclipse user hits cancel, but in GWT, it will result
      // in confusing errors later if we don't catch and handle it.
      throw abortException;
    }

    /**
     * Overrides the creation of the parser to use one that filters out elements annotated with
     * {@code GwtIncompatible}.
     */
    @Override
    public void initializeParser() {
      this.parser = new ParserImpl(this.problemReporter,
          this.options.parseLiteralExpressionsAsConstants);
    }

    @Override
    public void process(CompilationUnitDeclaration cud, int i) {
      try {
        super.process(cud, i);
      } catch (AbortCompilation e) {
        abortCount++;
        String filename = new String(cud.getFileName());
        logger.log(TreeLogger.WARN, "JDT aborted: " + filename + ": " + e.problem.getMessage());
        if (abortCount >= ABORT_COUNT_MAX) {
          logger.log(TreeLogger.ERROR, "JDT threw too many exceptions.");
          throw e;
        }
        return; // continue without it; it might be a server-side class.
      } catch (RuntimeException e) {
        abortCount++;
        String filename = new String(cud.getFileName());
        logger.log(TreeLogger.WARN, "JDT threw an exception: " + filename + ": " + e);
        if (abortCount >= ABORT_COUNT_MAX) {
          logger.log(TreeLogger.ERROR, "JDT threw too many exceptions.");
          throw new AbortCompilation(cud.compilationResult, e);
        }
        return; // continue without it; it might be a server-side class.
      }
      ClassFile[] classFiles = cud.compilationResult().getClassFiles();
      Map<ClassFile, CompiledClass> results = new LinkedHashMap<ClassFile, CompiledClass>();
      for (ClassFile classFile : classFiles) {
        createCompiledClass(classFile, results);
      }
      List<CompiledClass> compiledClasses = new ArrayList<CompiledClass>(results.values());
      addBinaryTypes(compiledClasses);

      ICompilationUnit icu = cud.compilationResult().compilationUnit;
      Adapter adapter = (Adapter) icu;
      CompilationUnitBuilder builder = adapter.getBuilder();

      // TODO(rluble): jsni method parsing should probably be done right after Java parsing, at
      // that moment the original list of imports is still present and this hack would not be
      // needed.
      assert parser instanceof ParserImpl;
      // Retrieve the original list of imports and dispose.
      List<ImportReference> cudOriginalImports =
          ((ParserImpl) parser).originalImportsByCud.removeAll(cud);
      processor.process(builder, cud, cudOriginalImports, compiledClasses);
    }

    /**
     * Recursively creates enclosing types first.
     */
    private void createCompiledClass(ClassFile classFile, Map<ClassFile, CompiledClass> results) {
      if (results.containsKey(classFile)) {
        // Already created.
        return;
      }
      CompiledClass enclosingClass = null;
      if (classFile.enclosingClassFile != null) {
        ClassFile enclosingClassFile = classFile.enclosingClassFile;
        createCompiledClass(enclosingClassFile, results);
        enclosingClass = results.get(enclosingClassFile);
        assert enclosingClass != null;
      }
      String internalName = CharOperation.charToString(classFile.fileName());
      String sourceName = JdtUtil.getSourceName(classFile.referenceBinding);
      // TODO(cromwellian) implement Retrolambda on output?
      CompiledClass result = new CompiledClass(classFile.getBytes(), enclosingClass,
          isLocalType(classFile), internalName, sourceName);
      results.put(classFile, result);
    }

    int getAbortCount() {
      return abortCount;
    }
  }

  /**
   * Hook point to accept results.
   */
  private static class ICompilerRequestorImpl implements ICompilerRequestor {
    @Override
    public void acceptResult(CompilationResult result) {
    }
  }

  /**
   * How JDT receives files from the environment.
   */
  private class INameEnvironmentImpl implements INameEnvironment {
    @Override
    public void cleanup() {
    }

    @Override
    public NameEnvironmentAnswer findType(char[] type, char[][] pkg) {
      return findType(CharOperation.arrayConcat(pkg, type));
    }

    @Override
    public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
      char[] internalNameChars = CharOperation.concatWith(compoundTypeName, '/');
      String internalName = String.valueOf(internalNameChars);

      // If we already know this is a package, take the shortcut.
      if (JreIndex.contains(internalName) || packages.contains(internalName)) {
        return null;
      }

      NameEnvironmentAnswer cachedAnswer = findTypeInCache(internalName);
      if (cachedAnswer != null) {
        return cachedAnswer;
      }

      NameEnvironmentAnswer additionalProviderAnswer = findTypeInAdditionalProvider(internalName);
      if (additionalProviderAnswer != null) {
        return additionalProviderAnswer;
      }

      NameEnvironmentAnswer classPathAnswer = findTypeInClassPath(internalName);

      if (classPathAnswer != null) {
        return classPathAnswer;
      }
      return null;
    }

    /*
      Generated from:

       public class LambdaMetafactory {
        public static CallSite metafactory(MethodHandles.Lookup caller, String invokedName,
            MethodType invokedType, MethodType samMethodType, MethodHandle implMethod,
            MethodType instantiatedMethodType) {
          return null;
        }

        public static CallSite altMetafactory(MethodHandles.Lookup caller, String invokedName,
            MethodType invokedType, Object... args) {
          return null;
        }
      }
     */
    private byte[] getLambdaMetafactoryBytes() {
      return BaseEncoding.base64().decode(
          "yv66vgAAADMAFwoAAwARBwASBwATAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJU"
          + "YWJsZQEAC21ldGFmYWN0b3J5BwAVAQAGTG9va3VwAQAMSW5uZXJDbGFzc2VzAQDMKExqYXZhL2xh"
          + "bmcvaW52b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwO0xqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xh"
          + "bmcvaW52b2tlL01ldGhvZFR5cGU7TGphdmEvbGFuZy9pbnZva2UvTWV0aG9kVHlwZTtMamF2YS9s"
          + "YW5nL2ludm9rZS9NZXRob2RIYW5kbGU7TGphdmEvbGFuZy9pbnZva2UvTWV0aG9kVHlwZTspTGph"
          + "dmEvbGFuZy9pbnZva2UvQ2FsbFNpdGU7AQAOYWx0TWV0YWZhY3RvcnkBAIYoTGphdmEvbGFuZy9p"
          + "bnZva2UvTWV0aG9kSGFuZGxlcyRMb29rdXA7TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9p"
          + "bnZva2UvTWV0aG9kVHlwZTtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvaW52b2tlL0Nh"
          + "bGxTaXRlOwEAClNvdXJjZUZpbGUBABZMYW1iZGFNZXRhZmFjdG9yeS5qYXZhDAAEAAUBACJqYXZh"
          + "L2xhbmcvaW52b2tlL0xhbWJkYU1ldGFmYWN0b3J5AQAQamF2YS9sYW5nL09iamVjdAcAFgEAJWph"
          + "dmEvbGFuZy9pbnZva2UvTWV0aG9kSGFuZGxlcyRMb29rdXABAB5qYXZhL2xhbmcvaW52b2tlL01l"
          + "dGhvZEhhbmRsZXMAIQACAAMAAAAAAAMAAQAEAAUAAQAGAAAAHQABAAEAAAAFKrcAAbEAAAABAAcA"
          + "AAAGAAEAAAAGAAkACAAMAAEABgAAABoAAQAGAAAAAgGwAAAAAQAHAAAABgABAAAAEACJAA0ADgAB"
          + "AAYAAAAaAAEABAAAAAIBsAAAAAEABwAAAAYAAQAAABUAAgAPAAAAAgAQAAsAAAAKAAEACQAUAAoA"
          + "GQ==");
    }

    /*
      Generated from:

      public class SerializedLambda {
        public SerializedLambda(Class<?> capturingClass,
                        String functionalInterfaceClass,
                        String functionalInterfaceMethodName,
                        String functionalInterfaceMethodSignature,
                        int implMethodKind,
                        String implClass,
                        String implMethodName,
                        String implMethodSignature,
                        String instantiatedMethodType,
                        Object[] capturedArgs) {
        }

        public String getCapturingClass() { return null; }
        public String getFunctionalInterfaceClass() { return null; }
        public String getFunctionalInterfaceMethodName() { return null; }
        public String getFunctionalInterfaceMethodSignature() { return null; }
        public String getImplClass() { return null; }
        public String getImplMethodName() { return null; }
        public String getImplMethodSignature() { return null; }
        public int getImplMethodKind() { return 0; }
        public final String getInstantiatedMethodType() { return null; }
        public int getCapturedArgCount() { return 0; }
        public Object getCapturedArg(int i) { return null; }
        public String toString() { return super.toString(); }
      }
     */
    private byte[] getSerializedLambdaBytes() {
      return BaseEncoding.base64().decode(
          "yv66vgAAADMAIQoABAAcCgAEAB0HAB4HAB8BAAY8aW5pdD4BAKYoTGphdmEvbGFuZy9DbGFzcztM"
          + "amF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztJTGph"
          + "dmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7TGphdmEv"
          + "bGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJs"
          + "ZQEACVNpZ25hdHVyZQEAqShMamF2YS9sYW5nL0NsYXNzPCo+O0xqYXZhL2xhbmcvU3RyaW5nO0xq"
          + "YXZhL2xhbmcvU3RyaW5nO0xqYXZhL2xhbmcvU3RyaW5nO0lMamF2YS9sYW5nL1N0cmluZztMamF2"
          + "YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztMamF2YS9sYW5nL1N0cmluZztbTGphdmEv"
          + "bGFuZy9PYmplY3Q7KVYBABFnZXRDYXB0dXJpbmdDbGFzcwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7"
          + "AQAbZ2V0RnVuY3Rpb25hbEludGVyZmFjZUNsYXNzAQAgZ2V0RnVuY3Rpb25hbEludGVyZmFjZU1l"
          + "dGhvZE5hbWUBACVnZXRGdW5jdGlvbmFsSW50ZXJmYWNlTWV0aG9kU2lnbmF0dXJlAQAMZ2V0SW1w"
          + "bENsYXNzAQARZ2V0SW1wbE1ldGhvZE5hbWUBABZnZXRJbXBsTWV0aG9kU2lnbmF0dXJlAQARZ2V0"
          + "SW1wbE1ldGhvZEtpbmQBAAMoKUkBABlnZXRJbnN0YW50aWF0ZWRNZXRob2RUeXBlAQATZ2V0Q2Fw"
          + "dHVyZWRBcmdDb3VudAEADmdldENhcHR1cmVkQXJnAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7AQAI"
          + "dG9TdHJpbmcBAApTb3VyY2VGaWxlAQAVU2VyaWFsaXplZExhbWJkYS5qYXZhDAAFACAMABkADAEA"
          + "IWphdmEvbGFuZy9pbnZva2UvU2VyaWFsaXplZExhbWJkYQEAEGphdmEvbGFuZy9PYmplY3QBAAMo"
          + "KVYAIQADAAQAAAAAAA0AAQAFAAYAAgAHAAAAIQABAAsAAAAFKrcAAbEAAAABAAgAAAAKAAIAAAAN"
          + "AAQADgAJAAAAAgAKAAEACwAMAAEABwAAABoAAQABAAAAAgGwAAAAAQAIAAAABgABAAAAEAABAA0A"
          + "DAABAAcAAAAaAAEAAQAAAAIBsAAAAAEACAAAAAYAAQAAABEAAQAOAAwAAQAHAAAAGgABAAEAAAAC"
          + "AbAAAAABAAgAAAAGAAEAAAASAAEADwAMAAEABwAAABoAAQABAAAAAgGwAAAAAQAIAAAABgABAAAA"
          + "EwABABAADAABAAcAAAAaAAEAAQAAAAIBsAAAAAEACAAAAAYAAQAAABQAAQARAAwAAQAHAAAAGgAB"
          + "AAEAAAACAbAAAAABAAgAAAAGAAEAAAAVAAEAEgAMAAEABwAAABoAAQABAAAAAgGwAAAAAQAIAAAA"
          + "BgABAAAAFgABABMAFAABAAcAAAAaAAEAAQAAAAIDrAAAAAEACAAAAAYAAQAAABcAEQAVAAwAAQAH"
          + "AAAAGgABAAEAAAACAbAAAAABAAgAAAAGAAEAAAAYAAEAFgAUAAEABwAAABoAAQABAAAAAgOsAAAA"
          + "AQAIAAAABgABAAAAGQABABcAGAABAAcAAAAaAAEAAgAAAAIBsAAAAAEACAAAAAYAAQAAABoAAQAZ"
          + "AAwAAQAHAAAAHQABAAEAAAAFKrcAArAAAAABAAgAAAAGAAEAAAAbAAEAGgAAAAIAGw==");
    }

    private NameEnvironmentAnswer findTypeInCache(String internalName) {
      if (!internalTypes.containsKey(internalName)) {
        return null;
      }

      try {
        return internalTypes.get(internalName).getNameEnvironmentAnswer();
      } catch (ClassFormatException ex) {
        return null;
      }
    }

    private NameEnvironmentAnswer findTypeInAdditionalProvider(String internalName) {
      if (additionalTypeProviderDelegate == null) {
        return null;
      }

      GeneratedUnit unit = additionalTypeProviderDelegate.doFindAdditionalType(internalName);
      if (unit == null) {
        return null;
      }

      return new NameEnvironmentAnswer(new Adapter(CompilationUnitBuilder.create(unit)), null);
    }

    private NameEnvironmentAnswer findTypeInClassPath(String internalName) {

      // If the class was previously queried here return the cached result.
      if (cachedClassPathAnswerByInternalName.containsKey(internalName)) {
        // The return might be null if the class was not found at all.
        return cachedClassPathAnswerByInternalName.get(internalName);
      }
      NameEnvironmentAnswer answer = doFindTypeInClassPath(internalName);
      // Here we cache the answer even if it is null to denote that it was not found.
      cachedClassPathAnswerByInternalName.put(internalName, answer);
      return answer;
    }

    private NameEnvironmentAnswer doFindTypeInClassPath(String internalName) {
      URL resource = getClassLoader().getResource(internalName + ".class");
      if (resource != null) {
        try (InputStream openStream = resource.openStream()) {

          ClassFileReader classFileReader =
              ClassFileReader.read(openStream, resource.toExternalForm(), true);
          // In case insensitive file systems we might have found a resource  whose name is different
          // in case and should not be returned as an answer.
          if (internalName.equals(CharOperation.charToString(classFileReader.getName()))) {
            return new NameEnvironmentAnswer(classFileReader, null);
          }
        } catch (IOException | ClassFormatException e) {
          // returns null indicating a failure.
        }
      }
      // LambdaMetafactory and SerializedLambda byte-code side-artifacts of JDT compile and actually
      // not referenced by our AST. However, these classes are only available in JDK8+ so
      // JdtCompiler fails to validate the classes that are referencing it. We tackle that by
      // providing a stub version if it is not found in the class path.
      if (internalName.equals("java/lang/invoke/LambdaMetafactory")) {
        try {
          ClassFileReader cfr = new ClassFileReader(getLambdaMetafactoryBytes(),
              "synthetic:java/lang/invoke/LambdaMetafactory".toCharArray(), true);
          return new NameEnvironmentAnswer(cfr, null);
        } catch (ClassFormatException e) {
          e.printStackTrace();
        }
      } else if (internalName.equals("java/lang/invoke/SerializedLambda")) {
        try {
          ClassFileReader cfr = new ClassFileReader(getSerializedLambdaBytes(),
              "synthetic:java/lang/invoke/SerializedLambda".toCharArray(), true);
          return new NameEnvironmentAnswer(cfr, null);
        } catch (ClassFormatException e) {
          e.printStackTrace();
        }
      }
      return null;
    }

    @Override
    public boolean isPackage(char[][] parentPkg, char[] pkg) {
      char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '/');
      String packageName = String.valueOf(pathChars);
      return isPackage(packageName);
    }

    private boolean isPackage(String slashedPackageName) {
      // Test the JRE explicitly, because the classloader trick doesn't work.
      if (JreIndex.contains(slashedPackageName)) {
        return true;
      }
      /*
       * TODO(zundel): When cached CompiledClass instances are used, 'packages'
       * does not contain all packages in the compile and this test fails the
       * test on some packages.
       *
       * This is supposed to work via the call chain:
       *
       * CSB.doBuildFrom -> CompileMoreLater.addValidUnit
       *    -> JdtCompiler.addCompiledUnit
       *    -> addPackages()
       */
      if (packages.contains(slashedPackageName)) {
        return true;
      }
      if (notPackages.contains(slashedPackageName)) {
        return false;
      }
      if ((additionalTypeProviderDelegate != null && additionalTypeProviderDelegate
          .doFindAdditionalPackage(slashedPackageName))) {
        addPackages(slashedPackageName);
        return true;
      }
      // Include class loader check for binary-only annotations.
      if (caseSensitivePathExists(slashedPackageName)) {
        addPackages(slashedPackageName);
        return true;
      } else {
        notPackages.add(slashedPackageName);
        return false;
      }
    }
  }

  /**
   * Compiles the given set of units. The units will be internally modified to
   * reflect the results of compilation. If the compiler aborts, logs an error
   * and throws UnableToCompleteException.
   */
  public static List<CompilationUnit> compile(TreeLogger logger, CompilerContext compilerContext,
      Collection<CompilationUnitBuilder> builders) throws UnableToCompleteException {
    Event jdtCompilerEvent = SpeedTracerLogger.start(CompilerEventType.JDT_COMPILER);

    try {
      DefaultUnitProcessor processor = new DefaultUnitProcessor();
      JdtCompiler compiler = new JdtCompiler(compilerContext, processor);
      compiler.doCompile(logger, builders);
      return processor.getResults();
    } finally {
      jdtCompilerEvent.end();
    }
  }

  public static CompilerOptions getStandardCompilerOptions() {
    CompilerOptions options = new CompilerOptions() {
      {
        warningThreshold.clearAll();
      }
    };

    long jdtSourceLevel = jdtLevelByGwtLevel.get(SourceLevel.DEFAULT_SOURCE_LEVEL);
    options.originalSourceLevel = jdtSourceLevel;
    options.complianceLevel = jdtSourceLevel;
    options.sourceLevel = jdtSourceLevel;
    options.targetJDK = jdtSourceLevel;

    // Generate debug info for debugging the output.
    options.produceDebugAttributes =
        ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_LINES
            | ClassFileConstants.ATTR_SOURCE;
    // Tricks like "boolean stopHere = true;" depend on this setting.
    options.preserveAllLocalVariables = true;
    // Let the JDT collect compilation unit dependencies
    options.produceReferenceInfo = true;

    // Turn off all warnings, saves some memory / speed.
    options.reportUnusedDeclaredThrownExceptionIncludeDocCommentReference = false;
    options.reportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable = false;
    options.inlineJsrBytecode = true;
    return options;
  }

  public CompilerOptions getCompilerOptions() {
    CompilerOptions options = getStandardCompilerOptions();
    long jdtSourceLevel = jdtLevelByGwtLevel.get(sourceLevel);

    options.originalSourceLevel = jdtSourceLevel;
    options.complianceLevel = jdtSourceLevel;
    options.sourceLevel = jdtSourceLevel;
    options.targetJDK = jdtSourceLevel;
    return options;
  }

  private static ReferenceBinding resolveType(LookupEnvironment lookupEnvironment,
      String sourceOrBinaryName) {
    ReferenceBinding type = null;

    int p = sourceOrBinaryName.indexOf('$');
    if (p > 0) {
      // resolve an outer type before trying to get the cached inner
      String cupName = sourceOrBinaryName.substring(0, p);
      char[][] chars = CharOperation.splitOn('.', cupName.toCharArray());
      ReferenceBinding outerType = lookupEnvironment.getType(chars);
      if (outerType != null) {
        // outer class was found
        resolveRecursive(outerType);
        chars = CharOperation.splitOn('.', sourceOrBinaryName.toCharArray());
        type = lookupEnvironment.getCachedType(chars);
        if (type == null) {
          // no inner type; this is a pure failure
          return null;
        }
      }
    } else {
      // just resolve the type straight out
      char[][] chars = CharOperation.splitOn('.', sourceOrBinaryName.toCharArray());
      type = lookupEnvironment.getType(chars);
    }

    if (type != null) {
      if (type instanceof UnresolvedReferenceBinding) {
        /*
         * Since type is an instance of UnresolvedReferenceBinding, we know that
         * the return value BinaryTypeBinding.resolveType will be of type
         * ReferenceBinding
         */
        type = (ReferenceBinding) BinaryTypeBinding.resolveType(type, lookupEnvironment, true);
      }
      // found it
      return type;
    }

    // Assume that the last '.' should be '$' and try again.
    //
    p = sourceOrBinaryName.lastIndexOf('.');
    if (p >= 0) {
      sourceOrBinaryName =
          sourceOrBinaryName.substring(0, p) + "$" + sourceOrBinaryName.substring(p + 1);
      return resolveType(lookupEnvironment, sourceOrBinaryName);
    }

    return null;
  }

  /**
   * Returns <code>true</code> if this is a local type, or if this type is
   * nested inside of any local type.
   */
  private static boolean isLocalType(ClassFile classFile) {
    SourceTypeBinding b = classFile.referenceBinding;
    while (!b.isStatic()) {
      if (b instanceof LocalTypeBinding) {
        return true;
      }
      b = ((NestedTypeBinding) b).enclosingType;
    }
    return false;
  }

  /**
   * Recursively invoking {@link ReferenceBinding#memberTypes()} causes JDT to
   * resolve and cache all nested types at arbitrary depth.
   */
  private static void resolveRecursive(ReferenceBinding outerType) {
    for (ReferenceBinding memberType : outerType.memberTypes()) {
      resolveRecursive(memberType);
    }
  }

  private AdditionalTypeProviderDelegate additionalTypeProviderDelegate;

  /**
   * Maps internal names to compiled classes.
   */
  private final Map<String, CompiledClass> internalTypes = new HashMap<String, CompiledClass>();

  /**
   * Remembers types that have been found in the classpath or not found at all to avoid unnecessary
   * resource scanning.
   */
  private final Map<String, NameEnvironmentAnswer> cachedClassPathAnswerByInternalName =
      Maps.newHashMap();

  /**
   * Remembers types that where not found during resolution to avoid unnecessary file scanning.
   */
  private final Set<String> unresolvableReferences = Sets.newHashSet();

  /**
   * Only active during a compile.
   */
  private transient CompilerImpl compilerImpl;

  private final Set<String> notPackages = new HashSet<String>();

  private final Set<String> packages = new HashSet<String>();

  private final UnitProcessor processor;

  /**
   * Java source level compatibility.
   */
  private final SourceLevel sourceLevel;

  private CompilerContext compilerContext;

  /**
   * Controls whether the compiler strips unused imports.
   */
  private static boolean removeUnusedImports = true;

  /**
   * Maps from SourceLevel, the GWT compiler Java source compatibility levels, to JDT
   * Java source compatibility levels.
   */
  private static final Map<SourceLevel, Long> jdtLevelByGwtLevel =
      ImmutableMap.<SourceLevel, Long>of(
          SourceLevel.JAVA8, ClassFileConstants.JDK1_8);

  public JdtCompiler(CompilerContext compilerContext, UnitProcessor processor) {
    this.compilerContext = compilerContext;
    this.processor = processor;
    this.sourceLevel = compilerContext.getOptions().getSourceLevel();
  }

  public void addCompiledUnit(CompilationUnit unit) {
    addPackages(Shared.getPackageName(unit.getTypeName()).replace('.', '/'));
    addBinaryTypes(unit.getCompiledClasses());
  }

  public ArrayList<String> collectApiRefs(final CompilationUnitDeclaration cud) {
    final Set<String> apiRefs = new HashSet<String>();
    class DependencyVisitor extends TypeRefVisitor {
      public DependencyVisitor() {
        super(cud);
      }

      @Override
      public boolean visit(Argument arg, BlockScope scope) {
        // Adapted from {@link Argument#traverse}.
        // Don't visit annotations.
        if (arg.type != null) {
          arg.type.traverse(this, scope);
        }
        return false;
      }

      @Override
      public boolean visit(Argument arg, ClassScope scope) {
        // Adapted from {@link Argument#traverse}.
        // Don't visit annotations.
        if (arg.type != null) {
          arg.type.traverse(this, scope);
        }
        return false;
      }

      @Override
      public boolean visit(Block block, BlockScope scope) {
        assert false : "Error in DepedencyVisitor; should never visit a block";
        return false;
      }

      @Override
      public boolean visit(Clinit clinit, ClassScope scope) {
        return false;
      }

      @Override
      public boolean visit(ConstructorDeclaration ctor, ClassScope scope) {
        if (ctor.typeParameters != null) {
          int typeParametersLength = ctor.typeParameters.length;
          for (int i = 0; i < typeParametersLength; i++) {
            ctor.typeParameters[i].traverse(this, ctor.scope);
          }
        }
        traverse(ctor);
        return false;
      }

      @Override
      public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
        // Don't visit javadoc.
        // Don't visit annotations.
        if (fieldDeclaration.type != null) {
          fieldDeclaration.type.traverse(this, scope);
        }
        // Don't visit initialization.
        return false;
      }

      @Override
      public boolean visit(Initializer initializer, MethodScope scope) {
        return false;
      }

      @Override
      public boolean visit(MethodDeclaration meth, ClassScope scope) {
        if (meth.typeParameters != null) {
          int typeParametersLength = meth.typeParameters.length;
          for (int i = 0; i < typeParametersLength; i++) {
            meth.typeParameters[i].traverse(this, meth.scope);
          }
        }
        if (meth.returnType != null) {
          meth.returnType.traverse(this, meth.scope);
        }
        traverse(meth);
        return false;
      }

      @Override
      public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
        traverse(typeDeclaration);
        return false;
      }

      @Override
      public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
        traverse(typeDeclaration);
        return false;
      }

      @Override
      protected void onMissingTypeRef(MissingTypeBinding referencedType,
          CompilationUnitDeclaration unitOfReferrer, Expression expression) {
        addReference(referencedType);
      }

      @Override
      protected void onBinaryTypeRef(BinaryTypeBinding referencedType,
          CompilationUnitDeclaration unitOfReferrer, Expression expression) {
        if (!String.valueOf(referencedType.getFileName()).endsWith(".java")) {
          // ignore binary-only annotations
          return;
        }
        addReference(referencedType);
      }

      @Override
      protected void onTypeRef(SourceTypeBinding referencedType,
          CompilationUnitDeclaration unitOfReferrer) {
        addReference(referencedType);
      }

      private void addReference(ReferenceBinding referencedType) {
        apiRefs.add(JdtUtil.getSourceName(referencedType));
      }

      /**
       * Adapted from {@link MethodDeclaration#traverse}.
       */
      private void traverse(AbstractMethodDeclaration meth) {
        // Don't visit javadoc.
        // Don't visit annotations.
        if (meth.arguments != null) {
          int argumentLength = meth.arguments.length;
          for (int i = 0; i < argumentLength; i++) {
            meth.arguments[i].traverse(this, meth.scope);
          }
        }
        if (meth.thrownExceptions != null) {
          int thrownExceptionsLength = meth.thrownExceptions.length;
          for (int i = 0; i < thrownExceptionsLength; i++) {
            meth.thrownExceptions[i].traverse(this, meth.scope);
          }
        }
        // Don't visit method bodies.
      }

      /**
       * Adapted from {@link TypeDeclaration#traverse}.
       */
      private void traverse(TypeDeclaration type) {
        // Don't visit javadoc.
        // Don't visit annotations.
        if (type.superclass != null) {
          type.superclass.traverse(this, type.scope);
        }
        if (type.superInterfaces != null) {
          int length = type.superInterfaces.length;
          for (int i = 0; i < length; i++) {
            type.superInterfaces[i].traverse(this, type.scope);
          }
        }
        if (type.typeParameters != null) {
          int length = type.typeParameters.length;
          for (int i = 0; i < length; i++) {
            type.typeParameters[i].traverse(this, type.scope);
          }
        }
        if (type.memberTypes != null) {
          int length = type.memberTypes.length;
          for (int i = 0; i < length; i++) {
            type.memberTypes[i].traverse(this, type.scope);
          }
        }
        if (type.fields != null) {
          int length = type.fields.length;
          for (int i = 0; i < length; i++) {
            FieldDeclaration field;
            if ((field = type.fields[i]).isStatic()) {
              field.traverse(this, type.staticInitializerScope);
            } else {
              field.traverse(this, type.initializerScope);
            }
          }
        }
        if (type.methods != null) {
          int length = type.methods.length;
          for (int i = 0; i < length; i++) {
            type.methods[i].traverse(this, type.scope);
          }
        }
      }
    }
    DependencyVisitor visitor = new DependencyVisitor();
    cud.traverse(visitor, cud.scope);
    ArrayList<String> result = new ArrayList<String>(apiRefs);
    Collections.sort(result);
    return result;
  }

  /**
   * Compiles source using the JDT. The {@link UnitProcessor#process} callback method will be called
   * once for each compiled file. If the compiler aborts, logs a message and throws
   * UnableToCompleteException.
   */
  public void doCompile(TreeLogger logger, Collection<CompilationUnitBuilder> builders)
      throws UnableToCompleteException {
    if (builders.isEmpty()) {
      return;
    }
    List<ICompilationUnit> icus = new ArrayList<ICompilationUnit>();
    for (CompilationUnitBuilder builder : builders) {
      addPackages(Shared.getPackageName(builder.getTypeName()).replace('.', '/'));
      icus.add(new Adapter(builder));
    }

    compilerImpl = new CompilerImpl(logger, getCompilerOptions());
    try {
      compilerImpl.compile(icus.toArray(new ICompilationUnit[icus.size()]));
    } catch (AbortCompilation e) {
      final String compilerAborted = String.format("JDT compiler aborted after %d errors",
          compilerImpl.getAbortCount());
      if (e.problem == null) {
        logger.log(TreeLogger.Type.ERROR, compilerAborted + ".");
      } else if (e.problem.getOriginatingFileName() == null) {
        logger.log(TreeLogger.Type.ERROR, compilerAborted + ": " + e.problem.getMessage());
      } else {
        String filename = new String(e.problem.getOriginatingFileName());
        TreeLogger branch = logger.branch(TreeLogger.Type.ERROR,
            "At " + filename + ": " + e.problem.getSourceLineNumber());
        branch.log(TreeLogger.Type.ERROR, compilerAborted + ": " + e.problem.getMessage());
      }
      throw new UnableToCompleteException();
    } finally {
      compilerImpl = null;
    }
  }

  public ReferenceBinding resolveType(String sourceOrBinaryName) {
    if (unresolvableReferences.contains(sourceOrBinaryName)) {
      return null;
    }
    ReferenceBinding typeBinding =
        resolveType(compilerImpl.lookupEnvironment, sourceOrBinaryName);
    if (typeBinding == null) {
      unresolvableReferences.add(sourceOrBinaryName);
    }
    return typeBinding;
  }

  public void setAdditionalTypeProviderDelegate(AdditionalTypeProviderDelegate newDelegate) {
    additionalTypeProviderDelegate = newDelegate;
  }

  /**
   * Sets whether the compiler should remove unused imports.
   */
  public static void setRemoveUnusedImports(boolean remove) {
    removeUnusedImports = remove;
  }

  private void addBinaryTypes(Collection<CompiledClass> compiledClasses) {
    for (CompiledClass cc : compiledClasses) {
      internalTypes.put(cc.getInternalName(), cc);
    }
  }

  private void addPackages(String slashedPackageName) {
    while (packages.add(slashedPackageName)) {
      int pos = slashedPackageName.lastIndexOf('/');
      if (pos > 0) {
        slashedPackageName = slashedPackageName.substring(0, pos);
      } else {
        packages.add("");
        break;
      }
    }
  }

  private static boolean caseSensitivePathExists(String resourcePath) {
    URL resourceURL = getClassLoader().getResource(resourcePath + '/');
    if (resourceURL == null) {
      return false;
    }

    try {
      File resourceFile = new File(resourceURL.toURI());
      return Arrays.asList(resourceFile.getParentFile().list()).contains(resourceFile.getName());
    } catch (URISyntaxException e) {
      // The URL can not be converted to a URI.
    } catch (IllegalArgumentException e) {
      // A file instance can not be constructed from a URI.
    }

    // Some exception occurred while trying to make sure the name for the resource on disk is
    // exactly the same as the one requested including case. If an exception is thrown in the
    // process we assume that the URI does not refer to a resource in the filesystem and that the
    // resource obtained from the classloader is the one requested.
    return true;
  }

  private static ClassLoader getClassLoader() {
    return Thread.currentThread().getContextClassLoader();
  }
}
