// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler;

import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.google.dart.compiler.CommandLineOptions.CompilerOptions;
import com.google.dart.compiler.LibraryDeps.Dependency;
import com.google.dart.compiler.UnitTestBatchRunner.Invocation;
import com.google.dart.compiler.ast.DartDirective;
import com.google.dart.compiler.ast.DartLibraryDirective;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartPartOfDirective;
import com.google.dart.compiler.ast.DartToSourceVisitor;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.ast.LibraryNode;
import com.google.dart.compiler.ast.LibraryUnit;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.metrics.CompilerMetrics;
import com.google.dart.compiler.metrics.DartEventType;
import com.google.dart.compiler.metrics.JvmMetrics;
import com.google.dart.compiler.metrics.Tracer;
import com.google.dart.compiler.metrics.Tracer.TraceEvent;
import com.google.dart.compiler.parser.DartParser;
import com.google.dart.compiler.resolver.CompileTimeConstantAnalyzer;
import com.google.dart.compiler.resolver.CoreTypeProvider;
import com.google.dart.compiler.resolver.CoreTypeProviderImplementation;
import com.google.dart.compiler.resolver.Element;
import com.google.dart.compiler.resolver.ElementKind;
import com.google.dart.compiler.resolver.Elements;
import com.google.dart.compiler.resolver.LibraryElement;
import com.google.dart.compiler.resolver.MemberBuilder;
import com.google.dart.compiler.resolver.MethodElement;
import com.google.dart.compiler.resolver.Resolver;
import com.google.dart.compiler.resolver.ResolverErrorCode;
import com.google.dart.compiler.resolver.SupertypeResolver;
import com.google.dart.compiler.resolver.TopLevelElementBuilder;
import com.google.dart.compiler.type.TypeAnalyzer;
import com.google.dart.compiler.util.DefaultTextOutput;
import com.google.dart.compiler.util.apache.StringUtils;

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Entry point for the Dart compiler.
 */
public class DartCompiler {

  public static final String EXTENSION_DEPS = "deps";
  public static final String EXTENSION_LOG = "log";
  public static final String EXTENSION_TIMESTAMP = "timestamp";

  public static final String CORELIB_URL_SPEC = "dart:core";
  public static final String MAIN_ENTRY_POINT_NAME = "main";

  private static class Compiler {
    private final LibrarySource app;
    private final List<LibrarySource> embeddedLibraries = new ArrayList<LibrarySource>();
    private final DartCompilerMainContext context;
    private final CompilerConfiguration config;
    private final Map<URI, LibraryUnit> libraries = new LinkedHashMap<URI, LibraryUnit>();
    private CoreTypeProvider typeProvider;
    private final boolean incremental;
    private final List<DartCompilationPhase> phases;
    private final LibrarySource coreLibrarySource;

    private Compiler(LibrarySource app, List<LibrarySource> embedded, CompilerConfiguration config,
        DartCompilerMainContext context) {
      this.app = app;
      this.config = config;
      this.phases = config.getPhases();
      this.context = context;
      for (LibrarySource library : embedded) {
        if (PackageLibraryManager.isDartSpec(library.getName())) {
          LibrarySource foundLibrary = context.getSystemLibraryFor(library.getName());
          assert(foundLibrary != null);
          embeddedLibraries.add(foundLibrary);
        } else {
          embeddedLibraries.add(library);
        }
      }
      coreLibrarySource = context.getSystemLibraryFor(CORELIB_URL_SPEC);
      assert(coreLibrarySource != null);
      embeddedLibraries.add(coreLibrarySource);

      incremental = config.incremental();
    }

    void addResolvedLibraries(Map<URI, LibraryUnit> resolvedLibraries) {
      libraries.putAll(resolvedLibraries);
    }

    Map<URI, LibraryUnit> getLibraries() {
      return libraries;
    }

    private void compile() {
      TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE) : null;
      try {
        updateAndResolve();
        if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) {
          return;
        }
        compileLibraries();
      } catch (IOException e) {
        context.onError(new DartCompilationError(app, DartCompilerErrorCode.IO, e.getMessage()));
      } finally {
        Tracer.end(logEvent);
      }
    }

    /**
     * Update the current application and any referenced libraries and resolve
     * them.
     *
     * @return a {@link LibraryUnit}, maybe <code>null</code>
     * @throws IOException on IO errors - the caller must log this if it cares
     */
    private LibraryUnit updateAndResolve() throws IOException {
      TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.UPDATE_RESOLVE) : null;

      CompilerMetrics compilerMetrics = context.getCompilerMetrics();
      if (compilerMetrics != null) {
        compilerMetrics.startUpdateAndResolveTime();
      }

      try {
        LibraryUnit library = updateLibraries(app);
        importEmbeddedLibraries();
        parseOutOfDateFiles();
        if (incremental) {
          addOutOfDateDeps();
        }
        if (!config.resolveDespiteParseErrors() && (context.getErrorCount() > 0)) {
          return library;
        }
        buildLibraryScopes();
        LibraryUnit corelibUnit = updateLibraries(coreLibrarySource);
        typeProvider = new CoreTypeProviderImplementation(corelibUnit.getElement().getScope(),
                                                          context);
        resolveLibraries();
        validateLibraryDirectives();
        return library;
      } finally {
        if(compilerMetrics != null) {
          compilerMetrics.endUpdateAndResolveTime();
        }

        Tracer.end(logEvent);
      }
    }

    /**
     * This method reads all libraries. They will be populated from some combination of fully-parsed
     * and diet-parser compilation units.
     */
    private void parseOutOfDateFiles() throws IOException {
      TraceEvent logEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.PARSE_OUTOFDATE) : null;
      CompilerMetrics compilerMetrics = context.getCompilerMetrics();
      long parseStart = compilerMetrics != null ? CompilerMetrics.getCPUTime() : 0;

      try {
        final Set<String> topLevelSymbolsDiff = Sets.newHashSet();
        for (LibraryUnit lib : getLibrariesToProcess()) {
          LibrarySource libSrc = lib.getSource();
          LibraryNode selfSourcePath = lib.getSelfSourcePath();

          // Load the existing DEPS, or create an empty one.
          LibraryDeps deps = lib.getDeps(context);
          Set<String> newUnitPaths = Sets.newHashSet();

          // Parse each compilation unit.
          for (LibraryNode sourcePathNode : lib.getSourcePaths()) {
            String relPath = sourcePathNode.getText();
            newUnitPaths.add(relPath);

            // Prepare DartSource for "#source" unit.
            final DartSource dartSrc = libSrc.getSourceFor(relPath);
            if (dartSrc == null || !dartSrc.exists()) {
              continue;
            }

            if (!incremental
                || PackageLibraryManager.isDartUri(libSrc.getUri())
                || isSourceOutOfDate(dartSrc)) {
              DartUnit unit = parse(dartSrc, lib.getPrefixes(),  false);
              // If we just parsed unit of library, report problems.
              if (sourcePathNode == selfSourcePath) {
                // report "#import" problems
                for (LibraryNode importPathNode : lib.getImportPaths()) {
                  LibrarySource dep = getImportSource(libSrc, importPathNode);
                  if (dep == null) {
                    reportMissingSource(context, libSrc, importPathNode);
                  }
                }
                // report "#source" problems
                for (LibraryNode checkSourcePathNode : lib.getSourcePaths()) {
                  String checkRelPath = checkSourcePathNode.getText();
                  final DartSource checkSource = libSrc.getSourceFor(checkRelPath);
                  if (checkSource == null || !checkSource.exists()) {
                    reportMissingSource(context, libSrc, checkSourcePathNode);
                  }
                }
              }

              // Process unit, if exists.
              if (unit != null) {
                if (sourcePathNode == selfSourcePath) {
                  lib.setSelfDartUnit(unit);
                }
                // Replace unit within the library.
                lib.putUnit(unit);
                context.setFilesHaveChanged();
                // Include into top-level symbols diff from current units, already existed or new.
                {
                  LibraryDeps.Source source = deps.getSource(relPath);
                  Set<String> newTopSymbols = unit.getTopDeclarationNames();
                  if (source != null) {
                    Set<String> oldTopSymbols = source.getTopSymbols();
                    SetView<String> diff0 = Sets.symmetricDifference(oldTopSymbols, newTopSymbols);
                    topLevelSymbolsDiff.addAll(diff0);
                  } else {
                    topLevelSymbolsDiff.addAll(newTopSymbols);
                  }
                }
              }
            } else {
              DartUnit dietUnit = parse(dartSrc, lib.getPrefixes(), true);
              if (dietUnit != null) {
                if (sourcePathNode == selfSourcePath) {
                  lib.setSelfDartUnit(dietUnit);
                }
                lib.putUnit(dietUnit);
              }
            }
          }

          // Include into top-level symbols diff from units which disappeared since last compiling.
          {
            Set<String> oldUnitPaths = deps.getUnitPaths();
            Set<String> disappearedUnitPaths = Sets.difference(oldUnitPaths, newUnitPaths);
            for (String relPath : disappearedUnitPaths) {
              LibraryDeps.Source source = deps.getSource(relPath);
              if (source != null) {
                Set<String> oldTopSymbols = source.getTopSymbols();
                topLevelSymbolsDiff.addAll(oldTopSymbols);
              }
            }
          }
        }

        // Parse units, which potentially depend on the difference in top-level symbols.
        if (!topLevelSymbolsDiff.isEmpty()) {
          context.setFilesHaveChanged();
          for (LibraryUnit lib : getLibrariesToProcess()) {
            LibrarySource libSrc = lib.getSource();
            LibraryNode selfSourcePath = lib.getSelfSourcePath();
            LibraryDeps deps = lib.getDeps(context);
            for (LibraryNode libNode : lib.getSourcePaths()) {
              String relPath = libNode.getText();
              // Prepare source dependency.
              LibraryDeps.Source source = deps.getSource(relPath);
              if (source == null) {
                continue;
              }
              // Check re-compilation conditions.
              if (source.shouldRecompileOnAnyTopLevelChange()
                  || !Sets.intersection(source.getAllSymbols(), topLevelSymbolsDiff).isEmpty()
                  || !Sets.intersection(source.getHoles(), topLevelSymbolsDiff).isEmpty()) {
                DartSource dartSrc = libSrc.getSourceFor(relPath);
                if (dartSrc == null || !dartSrc.exists()) {
                  continue;
                }
                DartUnit unit = parse(dartSrc, lib.getPrefixes(), false);
                if (unit != null) {
                  if (libNode == selfSourcePath) {
                    lib.setSelfDartUnit(unit);
                  } else {
                    lib.putUnit(unit);
                  }
                }
              }
            }
          }
        }
      } finally {
        if (compilerMetrics != null) {
          compilerMetrics.addParseWallTimeNano(CompilerMetrics.getCPUTime() - parseStart);
        }
        Tracer.end(logEvent);
      }
    }

    Collection<LibraryUnit> getLibrariesToProcess() {
      return libraries.values();
    }

    /**
     * This method reads the embedded library sources, making sure they are added
     * to the list of libraries to compile. It then adds the libraries as imports
     * of all libraries. The import is without prefix.
     */
    private void importEmbeddedLibraries() throws IOException {
      TraceEvent importEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.IMPORT_EMBEDDED_LIBRARIES) : null;
      try {
        for (LibrarySource embedded : embeddedLibraries) {
          updateLibraries(embedded);
        }

        for (LibraryUnit lib : getLibrariesToProcess()) {
          for (LibrarySource embedded : embeddedLibraries) {
            LibraryUnit imp = libraries.get(embedded.getUri());
            // Check that the current library is not the embedded library, and
            // that the current library does not already import the embedded
            // library.
            if (lib != imp && !lib.hasImport(imp)) {
              lib.addImport(imp, null);
            }
          }
        }
      } finally {
        Tracer.end(importEvent);
      }
    }

    /**
     * This method reads a library source and sets it up with its imports. When it
     * completes, it is guaranteed that {@link Compiler#libraries} will be completely populated.
     */
    private LibraryUnit updateLibraries(LibrarySource libSrc) throws IOException {
      TraceEvent updateEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.UPDATE_LIBRARIES, "name",
              libSrc.getName()) : null;
      try {
        // Avoid cycles.
        LibraryUnit lib = libraries.get(libSrc.getUri());
        if (lib != null) {
          return lib;
        }

        lib = context.getLibraryUnit(libSrc);
        // If we could not find the library, continue. The context will report
        // the error at the end.
        if (lib == null) {
          return null;
        }

        libraries.put(libSrc.getUri(), lib);

        // Update dependencies.
        for (LibraryNode libNode : lib.getImportPaths()) {
          LibrarySource dep = getImportSource(libSrc, libNode);
          if (dep != null) {
            LibraryUnit importedLib = updateLibraries(dep);
            lib.addImport(importedLib, libNode);
            if (libNode.isExported()) {
              lib.addExport(importedLib, libNode);
            }
          }
        }
        for (LibraryNode libNode : lib.getExportPaths()) {
          LibrarySource dep = getImportSource(libSrc, libNode);
          if (dep != null) {
            lib.addExport(updateLibraries(dep), libNode);
          }
        }
        return lib;
      } finally {
        Tracer.end(updateEvent);
      }
    }

    /**
     * @return the {@link LibrarySource} referenced in the "#import" from "libSrc". May be
     *         <code>null</code> if invalid URI or not existing library.
     */
    private LibrarySource getImportSource(LibrarySource libSrc, LibraryNode libNode)
        throws IOException {
      String libSpec = libNode.getText();
      LibrarySource dep;
      if (PackageLibraryManager.isDartSpec(libSpec)) {
        dep = context.getSystemLibraryFor(libSpec);
      } else {
        dep = libSrc.getImportFor(libSpec);
      }
      if (dep == null || !dep.exists()) {
        return null;
      }
      return dep;
    }

    /**
     * Determines whether the given source is out-of-date with respect to its artifacts.
     */
    private boolean isSourceOutOfDate(DartSource dartSrc) {
      TraceEvent logEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.IS_SOURCE_OUTOFDATE, "src",
              dartSrc.getName()) : null;

      try {
        // If incremental compilation is disabled, just return true to force all
        // units to be recompiled.
        if (!incremental) {
          return true;
        }

        TraceEvent timestampEvent =
            Tracer.canTrace() ? Tracer.start(
                DartEventType.TIMESTAMP_OUTOFDATE,
                "src",
                dartSrc.getName()) : null;
        try {
          return context.isOutOfDate(dartSrc, dartSrc, EXTENSION_TIMESTAMP);
        } finally {
          Tracer.end(timestampEvent);
        }
      } finally {
        Tracer.end(logEvent);
      }
    }

    /**
     * Build scopes for the given libraries.
     */
    private void buildLibraryScopes() {
      TraceEvent logEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.BUILD_LIB_SCOPES) : null;
      try {
        Collection<LibraryUnit> libs = getLibrariesToProcess();

        // Build the class elements declared in the sources of a library.
        // Loop can be parallelized.
        for (LibraryUnit lib : libs) {
          new TopLevelElementBuilder().exec(lib, context);
        }

        // The library scope can then be constructed, containing types declared
        // in the library, and types declared in the imports. Loop can be parallelized.
        for (LibraryUnit lib : libs) {
          new TopLevelElementBuilder().fillInLibraryScope(lib, context);
        }
      } finally {
        Tracer.end(logEvent);
      }
    }

    /**
     * Parses compilation units that are out-of-date with respect to their dependencies.
     */
    private void addOutOfDateDeps() throws IOException {
      TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.ADD_OUTOFDATE) : null;
      try {
        boolean filesHaveChanged = false;
        for (LibraryUnit lib : getLibrariesToProcess()) {

          // Load the existing DEPS, or create an empty one.
          LibraryDeps deps = lib.getDeps(context);

          // Prepare all top-level symbols.
          Set<String> oldTopLevelSymbols = Sets.newHashSet();
          for (LibraryDeps.Source source : deps.getSources()) {
            oldTopLevelSymbols.addAll(source.getTopSymbols());
          }

          // Parse units that are out-of-date with respect to their dependencies.
          for (DartUnit unit : lib.getUnits()) {
            if (unit.isDiet()) {
              String relPath = ((DartSource) unit.getSourceInfo().getSource()).getRelativePath();
              LibraryDeps.Source source = deps.getSource(relPath);
              if (isUnitOutOfDate(lib, source)) {
                filesHaveChanged = true;
                DartSource dartSrc = lib.getSource().getSourceFor(relPath);
                if (dartSrc != null && dartSrc.exists()) {
                  unit = parse(dartSrc, lib.getPrefixes(), false);
                  if (unit != null) {
                    lib.putUnit(unit);
                  }
                }
              }
            }
          }
        }

        if (filesHaveChanged) {
          context.setFilesHaveChanged();
        }
      } finally {
        Tracer.end(logEvent);
      }
    }

    /**
     * Determines whether the given dependencies are out-of-date.
     */
    private boolean isUnitOutOfDate(LibraryUnit lib, LibraryDeps.Source source) {
      // If we don't have dependency information, then we can not be sure that nothing changed.
      if (source == null) {
        return true;
      }
      // Check all dependencies.
      for (Dependency dep : source.getDeps()) {
        LibraryUnit depLib = libraries.get(dep.getLibUri());
        if (depLib == null) {
          return true;
        }
        // Prepare unit.
        DartUnit depUnit = depLib.getUnit(dep.getUnitName());
        if (depUnit == null) {
          return true;
        }
        // May be unit modified.
        if (depUnit.getSourceInfo().getSource().getLastModified() != dep.getLastModified()) {
          return true;
        }
      }
      // No changed dependencies.
      return false;
    }

    /**
     * Resolve all libraries. Assume that all library scopes are already built.
     */
    private void resolveLibraries() {
      TraceEvent logEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.RESOLVE_LIBRARIES) : null;
      try {
        // TODO(jgw): Optimization: Skip work for libraries that have nothing to
        // compile.

        // Resolve super class chain, and build the member elements. Both passes
        // need the library scope to be setup. Each for loop can be
        // parallelized.
        for (LibraryUnit lib : getLibrariesToProcess()) {
          for (DartUnit unit : lib.getUnits()) {
            // These two method calls can be parallelized.
            new SupertypeResolver().exec(unit, context, getTypeProvider());
            new MemberBuilder().exec(unit, context, getTypeProvider());
          }
        }

      } finally {
        Tracer.end(logEvent);
      }
    }

    private void validateLibraryDirectives() {
      for (LibraryUnit lib : getLibrariesToProcess()) {
        // don't need to validate system libraries
        if (PackageLibraryManager.isDartUri(lib.getSource().getUri())) {
          continue;
        }
        
        // check for #source uniqueness
        {
          Set<URI> includedSourceUris = Sets.newHashSet();
          for (LibraryNode sourceNode : lib.getSourcePaths()) {
            String path = sourceNode.getText();
            DartSource source = lib.getSource().getSourceFor(path);
            if (source != null) {
              URI uri = source.getUri();
              if (includedSourceUris.contains(uri)) {
                context.onError(new DartCompilationError(sourceNode.getSourceInfo(),
                    DartCompilerErrorCode.UNIT_WAS_ALREADY_INCLUDED, uri));
              }
              includedSourceUris.add(uri);
            }
          }
        }

        // Validate imports.
        boolean hasIO = false;
        boolean hasHTML = false;
        for (LibraryNode importNode : lib.getImportPaths()) {
          String libSpec = importNode.getText();
          String prefix = importNode.getPrefix();
          hasIO |= "dart:io".equals(libSpec);
          hasHTML |= "dart:html".equals(libSpec);
          // "dart:mirrors" are not done yet
          if ("dart:mirrors".equals(libSpec)) {
            context.onError(new DartCompilationError(importNode,
                DartCompilerErrorCode.MIRRORS_NOT_FULLY_IMPLEMENTED));
          }
          // validate import prefix
          if (DartParser.PSEUDO_KEYWORDS_SET.contains(prefix)) {
            context.onError(new DartCompilationError(importNode.getSourceInfo(),
                ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_IMPORT_PREFIX, prefix));
          }
          // validate console/web mix
          if (hasIO && hasHTML) {
            context.onError(new DartCompilationError(importNode.getSourceInfo(),
                DartCompilerErrorCode.CONSOLE_WEB_MIX));
          }
        }

        // check that each imported library has a library directive
        for (LibraryUnit importedLib  : lib.getImportedLibraries()) {

          if (PackageLibraryManager.isDartUri(importedLib.getSource().getUri())) {
            // system libraries are always valid
            continue;
          }

          // get the dart unit corresponding to this library
          DartUnit unit = importedLib.getSelfDartUnit();
          if (unit == null || unit.isDiet()) {
            // don't need to check a unit that hasn't changed
            continue;
          }

          boolean foundLibraryDirective = false;
          for (DartDirective directive : unit.getDirectives()) {
            if (directive instanceof DartLibraryDirective) {
              foundLibraryDirective = true;
              break;
            }
          }
          if (!foundLibraryDirective) {
            // find the imported path node (which corresponds to the import directive node)
            SourceInfo info = null;
            for (LibraryNode importPath : lib.getImportPaths()) {
              if (importPath.getText().equals(importedLib.getSelfSourcePath().getText())) {
                info = importPath.getSourceInfo();
                break;
              }
            }
            if (info != null) {
              context.onError(new DartCompilationError(info,
                  DartCompilerErrorCode.MISSING_LIBRARY_DIRECTIVE,
                  ((DartSource) unit.getSourceInfo().getSource()).getRelativePath()));
            }
          }
        }

        // check that all sourced units have no directives
        for (DartUnit unit : lib.getUnits()) {
          // don't need to check a unit that hasn't changed
          if (unit.isDiet()) {
            continue;
          }
          // ignore library unit
          DartSource unitSource = (DartSource) unit.getSourceInfo().getSource();
          if (isLibrarySelfUnit(lib, unitSource)) {
            continue;
          }
          // analyze directives
          List<DartDirective> directives = unit.getDirectives();
          if (directives.isEmpty()) {
            // TODO(scheglov) Remove after http://code.google.com/p/dart/issues/detail?id=6121
            if (!StringUtils.startsWith(lib.getName(), "dart:")) {
              context.onError(new DartCompilationError(unitSource,
                  DartCompilerErrorCode.MISSING_PART_OF_DIRECTIVE, lib.getName()));
            }
          } else if (directives.size() == 1 && directives.get(0) instanceof DartPartOfDirective) {
            DartPartOfDirective directive = (DartPartOfDirective) directives.get(0);
            String dirName = directive.getLibraryName();
            if (!Objects.equal(dirName, lib.getName())) {
              context.onError(new DartCompilationError(directive,
                  DartCompilerErrorCode.WRONG_PART_OF_NAME, lib.getName(), dirName));
            }
          } else {
            context.onError(new DartCompilationError(directives.get(0),
                DartCompilerErrorCode.ILLEGAL_DIRECTIVES_IN_SOURCED_UNIT,
                Elements.getRelativeSourcePath(unitSource, lib.getSource())));
          }
        }
      }
    }

    private static boolean isLibrarySelfUnit(LibraryUnit lib, DartSource unitSource) {
      String unitRelativePath = unitSource.getRelativePath();
      for (LibraryNode sourceNode : lib.getSourcePaths()) {
        if (unitRelativePath.equals(sourceNode.getText())) {
          if (sourceNode == lib.getSelfSourcePath()) {
            return true;
          }
          return false;
        }
      }
      return false;
    }

    private void setEntryPoint() {
      LibraryUnit lib = context.getAppLibraryUnit();
      lib.setEntryNode(new LibraryNode(MAIN_ENTRY_POINT_NAME));
      // this ensures that if we find it, it's a top-level static element
      Element element = lib.getElement().lookupLocalElement(MAIN_ENTRY_POINT_NAME);
      switch (ElementKind.of(element)) {
        case NONE:
          // this is ok, it might just be a library
          break;

        case METHOD:
          MethodElement methodElement = (MethodElement) element;
          Modifiers modifiers = methodElement.getModifiers();
          if (modifiers.isGetter()) {
            context.onError(new DartCompilationError(element,
                DartCompilerErrorCode.ENTRY_POINT_METHOD_MAY_NOT_BE_GETTER, MAIN_ENTRY_POINT_NAME));
          } else if (modifiers.isSetter()) {
            context.onError(new DartCompilationError(element,
                DartCompilerErrorCode.ENTRY_POINT_METHOD_MAY_NOT_BE_SETTER, MAIN_ENTRY_POINT_NAME));
          } else if (methodElement.getParameters().size() > 0) {
            context.onError(new DartCompilationError(element,
                DartCompilerErrorCode.ENTRY_POINT_METHOD_CANNOT_HAVE_PARAMETERS,
                MAIN_ENTRY_POINT_NAME));
          } else {
            lib.getElement().setEntryPoint(methodElement);
          }
          break;

        default:
          context.onError(new DartCompilationError(element,
              ResolverErrorCode.NOT_A_STATIC_METHOD, MAIN_ENTRY_POINT_NAME));
          break;
      }
    }

    private void compileLibraries() throws IOException {
      TraceEvent logEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE_LIBRARIES) : null;

      CompilerMetrics compilerMetrics = context.getCompilerMetrics();
      if (compilerMetrics != null) {
        compilerMetrics.startCompileLibrariesTime();
      }

      try {
        // Set entry point
        setEntryPoint();

        // The two following for loops can be parallelized.
        for (LibraryUnit lib : getLibrariesToProcess()) {
          boolean persist = false;

          // Compile all the units in this library.
          for (DartCompilationPhase phase : phases) {

            // Run all compiler phases including AST simplification and symbol
            // resolution. This must run in serial.
            for (DartUnit unit : lib.getUnits()) {
              
              // Don't compile diet units.
              if (unit.isDiet()) {
                continue;
              }

              unit = phase.exec(unit, context, getTypeProvider());
              if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) {
                return;
              }
            }

          }

          for (DartUnit unit : lib.getUnits()) {
            if (unit.isDiet()) {
              continue;
            }
            updateAnalysisTimestamp(unit);
            // To help support the IDE, notify the listener that this unit is compiled.
            context.unitCompiled(unit);
            // Update deps.
            lib.getDeps(context).update(context, unit);
            // We analyzed something, so we need to persist the deps.
            persist = true;
          }

          // Persist the DEPS file.
          if (persist) {
            lib.writeDeps(context);
          }
        }
      } finally {
        if (compilerMetrics != null) {
          compilerMetrics.endCompileLibrariesTime();
        }
        Tracer.end(logEvent);
      }
    }

    private void updateAnalysisTimestamp(DartUnit unit) throws IOException {
      // Update timestamp.
      Writer writer =
          context.getArtifactWriter(unit.getSourceInfo().getSource(), "", EXTENSION_TIMESTAMP);
      String timestampData = String.format("%d\n", System.currentTimeMillis());
      writer.write(timestampData);
      writer.close();
    }

    DartUnit parse(DartSource dartSrc, Set<String> libraryPrefixes, boolean diet) throws IOException {
      TraceEvent parseEvent =
          Tracer.canTrace() ? Tracer.start(DartEventType.PARSE, "src", dartSrc.getName()) : null;
      CompilerMetrics compilerMetrics = context.getCompilerMetrics();
      long parseStart = compilerMetrics != null ? CompilerMetrics.getThreadTime() : 0;
      Reader r = dartSrc.getSourceReader();
      String srcCode;
      boolean failed = true;
      try {
        try {
          srcCode = CharStreams.toString(r);
          failed = false;
        } finally {
          Closeables.close(r, failed);
        }

        DartParser parser = new DartParser(dartSrc, srcCode, diet, libraryPrefixes, context,
            context.getCompilerMetrics());
        DartUnit unit = parser.parseUnit();
        if (compilerMetrics != null) {
          compilerMetrics.addParseTimeNano(CompilerMetrics.getThreadTime() - parseStart);
        }

        if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) {
          // We don't return this unit, so no more processing expected for it.
          context.unitCompiled(unit);
          return null;
        }
        return unit;
      } finally {
        Tracer.end(parseEvent);
      }
    }

    private void reportMissingSource(DartCompilerContext context,
                                     LibrarySource libSrc,
                                     LibraryNode libNode) {
      if (libNode != null && StringUtils.startsWith(libNode.getText(), "dart-ext:")) {
        return;
      }
      DartCompilationError event = new DartCompilationError(libNode,
                                                            DartCompilerErrorCode.MISSING_SOURCE,
                                                            libNode.getText());
      event.setSource(libSrc);
      context.onError(event);
    }
    CoreTypeProvider getTypeProvider() {
      typeProvider.getClass(); // Quick null check.
      return typeProvider;
    }
  }

  /**
   * Provides cached parse and resolution results during selective compilation
   */
  public abstract static class SelectiveCache {

    /**
     * Answer the cached resolved libraries
     * 
     * @return a mapping (not <code>null</code>) of library source URI to cached {@link LibraryUnit}
     */
    public abstract Map<URI, LibraryUnit> getResolvedLibraries();

    /**
     * Answer the cached unresolved {@link DartUnit} for the specified source
     * 
     * @param dartSrc the source (not <code>null</code>)
     * @return the cached unit or <code>null</code> if it is not cached
     */
    public abstract DartUnit getUnresolvedDartUnit(DartSource dartSrc);
  }

  /**
   * Selectively compile a library. Use supplied libraries and ASTs when available.
   * This allows programming tools to provide customized ASTs for code that is currently being
   * edited, and may not compile correctly.
   */
  static class SelectiveCompiler extends Compiler {
    private final SelectiveCache selectiveCache;
    private Collection<LibraryUnit> librariesToProcess;

    private SelectiveCompiler(LibrarySource app, SelectiveCache selectiveCache,
        CompilerConfiguration config, DartCompilerMainContext context) {
      super(app, Collections.<LibrarySource>emptyList(), config, context);
      this.selectiveCache = selectiveCache;
      addResolvedLibraries(selectiveCache.getResolvedLibraries());
    }

    @Override
    Collection<LibraryUnit> getLibrariesToProcess() {
      if (librariesToProcess == null) {
        librariesToProcess = new ArrayList<LibraryUnit>();
        librariesToProcess.addAll(super.getLibrariesToProcess());
        librariesToProcess.removeAll(selectiveCache.getResolvedLibraries().values());
      }
      return librariesToProcess;
    }

    @Override
    DartUnit parse(DartSource dartSrc, Set<String> prefixes, boolean diet) throws IOException {
      DartUnit parsedUnit = selectiveCache.getUnresolvedDartUnit(dartSrc);
      if (parsedUnit != null) {
        return parsedUnit;
      }
      return super.parse(dartSrc, prefixes, diet);
    }
  }

  private static CompilerOptions processCommandLineOptions(String[] args) {
    CmdLineParser cmdLineParser = null;
    CompilerOptions compilerOptions = null;
    try {
      compilerOptions = new CompilerOptions();
      cmdLineParser = CommandLineOptions.parse(args, compilerOptions);
      if (args.length == 0 || compilerOptions.showHelp()) {
        showUsage(cmdLineParser, System.err);
        System.exit(1);
      }
    } catch (CmdLineException e) {
      System.err.println(e.getLocalizedMessage());
      showUsage(cmdLineParser, System.err);
      System.exit(1);
    }

    assert compilerOptions != null;
    return compilerOptions;
  }

  public static void main(final String[] topArgs) {
    Tracer.init();

    CompilerOptions topCompilerOptions = processCommandLineOptions(topArgs);
    boolean result = false;
    try {
      if (topCompilerOptions.showVersion()) {
        showVersion(topCompilerOptions);
        System.exit(0);
      }
      if (topCompilerOptions.shouldBatch()) {
        if (topArgs.length > 1) {
          System.err.println("(Extra arguments specified with -batch ignored.)");
        }
        result = UnitTestBatchRunner.runAsBatch(topArgs, new Invocation() {
          @Override
          public boolean invoke(String[] lineArgs) throws Throwable {
            List<String> allArgs = new ArrayList<String>();
            for (String arg: topArgs) {
              if (!arg.equals("-batch")) {
                allArgs.add(arg);
              }
            }
            for (String arg: lineArgs) {
              allArgs.add(arg);
            }

            CompilerOptions compilerOptions = processCommandLineOptions(
                allArgs.toArray(new String[allArgs.size()]));
            if (compilerOptions.shouldBatch()) {
              System.err.println("-batch ignored: Already in batch mode.");
            }
            return compilerMain(compilerOptions);
          }
        });
      } else {
        result = compilerMain(topCompilerOptions);
      }
    } catch (Throwable t) {
      t.printStackTrace();
      crash();
    }
    if (!result) {
      System.exit(1);
    }
  }

  /**
   * Invoke the compiler to build single application.
   *
   * @param compilerOptions parsed command line arguments
   *
   * @return <code> true</code> on success, <code>false</code> on failure.
   */
  public static boolean compilerMain(CompilerOptions compilerOptions) throws IOException {
    List<String> sourceFiles = compilerOptions.getSourceFiles();
    if (sourceFiles.size() == 0) {
      System.err.println("dart_analyzer: no source files were specified.");
      showUsage(null, System.err);
      return false;
    }

    File sourceFile = new File(sourceFiles.get(0));
    if (!sourceFile.exists()) {
      System.err.println("dart_analyzer: file not found: " + sourceFile);
      showUsage(null, System.err);
      return false;
    }

    CompilerConfiguration config = new DefaultCompilerConfiguration(compilerOptions);
    config.getPackageLibraryManager().setPackageRoots(Arrays.asList(new File[]{compilerOptions.getPackageRoot()}));
    return compilerMain(sourceFile, config);
  }

  /**
   * Invoke the compiler to build single application.
   *
   * @param sourceFile file passed on the command line to build
   * @param config compiler configuration built from parsed command line options
   *
   * @return <code> true</code> on success, <code>false</code> on failure.
   */
  public static boolean compilerMain(File sourceFile, CompilerConfiguration config)
      throws IOException {
    String errorMessage = compileApp(sourceFile, config);
    if (errorMessage != null) {
      System.err.println(errorMessage);
      return false;
    }

    TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.WRITE_METRICS) : null;
    try {
      maybeShowMetrics(config);
    } finally {
      Tracer.end(logEvent);
    }
    return true;
  }

  public static void crash() {
    // Our test scripts look for 253 to signal a "crash".
    System.exit(253);
  }

  private static void showUsage(CmdLineParser cmdLineParser, PrintStream out) {
    out.println("Usage: dart_analyzer [<options>] <dart-script> [script-arguments]");
    out.println("Available options:");
    if (cmdLineParser == null) {
      cmdLineParser = new CmdLineParser(new CompilerOptions());
    }
    cmdLineParser.printUsage(out);
  }

  private static void maybeShowMetrics(CompilerConfiguration config) {
    CompilerMetrics compilerMetrics = config.getCompilerMetrics();
    if (compilerMetrics != null) {
      compilerMetrics.write(System.out);
    }

    JvmMetrics.maybeWriteJvmMetrics(System.out, config.getJvmMetricOptions());
  }

  /**
   * Treats the <code>sourceFile</code> as the top level library and generates compiled output by
   * linking the dart source in this file with all libraries referenced with <code>#import</code>
   * statements.
   */
  public static String compileApp(File sourceFile, CompilerConfiguration config) throws IOException {
    TraceEvent logEvent =
        Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE_APP, "src", sourceFile.toString())
            : null;
    try {
      File outputDirectory = config.getOutputDirectory();
      DefaultDartArtifactProvider provider = new DefaultDartArtifactProvider(outputDirectory);
      // Compile the Dart application and its dependencies.
      PackageLibraryManager libraryManager = config.getPackageLibraryManager();
      final LibrarySource lib = new UrlLibrarySource(sourceFile.toURI(),libraryManager);
      DefaultDartCompilerListener listener;
      if (config.getCompilerOptions().showSourceFromAst()) {
        listener = new DefaultDartCompilerListener(config.printErrorFormat()) {
          @Override
          public void unitCompiled(DartUnit unit) {
            if (unit.getLibrary() != null) {
              if (unit.getLibrary().getSource() == lib) {
                DefaultTextOutput output = new DefaultTextOutput(false);
                unit.accept(new DartToSourceVisitor(output));
                System.out.println(output.toString());
              }
            }
          }
        };
      } else {
        listener = new DefaultDartCompilerListener(config.printErrorFormat());
      }
      String errorString = compileLib(lib, config, provider, listener);
      return errorString;
    } finally {
      Tracer.end(logEvent);
    }
  }

  /**
   * Compiles the given library, translating all its source files, and those
   * of its imported libraries, transitively.
   *
   * @param lib The library to be compiled (not <code>null</code>)
   * @param config The compiler configuration specifying the compilation phases
   * @param provider A mechanism for specifying where code should be generated
   * @param listener An object notified when compilation errors occur
   */
  public static String compileLib(LibrarySource lib, CompilerConfiguration config,
      DartArtifactProvider provider, DartCompilerListener listener) throws IOException {
    return compileLib(lib, Collections.<LibrarySource>emptyList(), config, provider, listener);
  }

  /**
   * Same method as above, but also takes a list of libraries that should be
   * implicitly imported by all libraries. These libraries are provided by the embedder.
   */
  public static String compileLib(LibrarySource lib,
                                  List<LibrarySource> embeddedLibraries,
                                  CompilerConfiguration config,
                                  DartArtifactProvider provider,
                                  DartCompilerListener listener) throws IOException {
    DartCompilerMainContext context = new DartCompilerMainContext(lib, provider, listener,
                                                                  config);
    new Compiler(lib, embeddedLibraries, config, context).compile();
    int errorCount = context.getErrorCount();
    if (config.typeErrorsAreFatal()) {
      errorCount += context.getTypeErrorCount();
    }
    if (config.warningsAreFatal()) {
      errorCount += context.getWarningCount();
    }
    if (errorCount > 0) {
      return "Compilation failed with " + errorCount
          + (errorCount == 1 ? " problem." : " problems.");
    }
    if (!context.getFilesHaveChanged()) {
      return null;
    }
    // Write checking log.
    {
      Writer writer = provider.getArtifactWriter(lib, "", EXTENSION_LOG);
      boolean threw = true;
      try {
        writer.write(String.format("Checked %s and found:%n", lib.getName()));
        writer.write(String.format("  no load/resolution errors%n"));
        writer.write(String.format("  %s type errors%n", context.getTypeErrorCount()));
        threw = false;
      } finally {
        Closeables.close(writer, threw);
      }
    }
    return null;
  }

  /**
   * Analyzes the given library and all its transitive dependencies.
   *
   * @param lib The library to be analyzed
   * @param parsedUnits A collection of unresolved ASTs that should be used
   * instead of parsing the associated source from storage. Intended for
   * IDE use when modified buffers must be analyzed. AST nodes in the map may be
   * ignored if not referenced by {@code lib}. (May be null.)
   * @param config The compiler configuration (phases will not be used), but resolution and
   * type-analysis will be invoked
   * @param provider A mechanism for specifying where code should be generated
   * @param listener An object notified when compilation errors occur
   * @throws NullPointerException if any of the arguments except {@code parsedUnits}
   * are {@code null}
   * @throws IOException on IO errors, which are not logged
   */
  public static LibraryUnit analyzeLibrary(LibrarySource lib, final Map<URI, DartUnit> parsedUnits,
      CompilerConfiguration config, DartArtifactProvider provider, DartCompilerListener listener)
      throws IOException {
    final PackageLibraryManager manager = config.getPackageLibraryManager();
    final HashMap<URI, LibraryUnit> resolvedLibs = new HashMap<URI, LibraryUnit>();
    SelectiveCache selectiveCache = new SelectiveCache() {
      @Override
      public Map<URI, LibraryUnit> getResolvedLibraries() {
        return resolvedLibs;
      }
      @Override
      public DartUnit getUnresolvedDartUnit(DartSource dartSrc) {
        if (parsedUnits == null) {
          return null;
        }
        URI srcUri = dartSrc.getUri();
        DartUnit parsedUnit = parsedUnits.remove(srcUri);
        if (parsedUnit != null) {
          return parsedUnit;
        }
        URI fileUri = manager.resolveDartUri(srcUri);
        return parsedUnits.remove(fileUri);
      }
    };
    Map<URI, LibraryUnit> libraryUnit = analyzeLibraries(lib, selectiveCache, config,
        provider, listener, false);
    return libraryUnit != null ? libraryUnit.get(lib.getUri()) : null;
  }

  /**
   * Analyzes the given library and all its transitive dependencies.
   *
   * @param lib The library to be analyzed
   * @param selectiveCache Provides cached parse and resolution results 
   *    during selective compilation (not <code>null</code>)
   * @param config The compiler configuration (phases and backends
   *    will not be used), but resolution and type-analysis will be invoked
   * @param provider A mechanism for specifying where code should be generated
   * @param listener An object notified when compilation errors occur
   * @param resolveAllNewLibs <code>true</code> if all new libraries should be resolved
   *    or false if only the library specified by the "lib" parameter should be resolved
   * @throws NullPointerException if any of the arguments except {@code parsedUnits}
   *    are {@code null}
   * @throws IOException on IO errors, which are not logged
   */
  public static Map<URI, LibraryUnit> analyzeLibraries(LibrarySource lib,
      SelectiveCache selectiveCache, CompilerConfiguration config,
      DartArtifactProvider provider, DartCompilerListener listener, 
      boolean resolveAllNewLibs) throws IOException {
    lib.getClass(); // Quick null check.
    provider.getClass(); // Quick null check.
    listener.getClass(); // Quick null check.
    Map<URI, LibraryUnit> resolvedLibs = selectiveCache.getResolvedLibraries();
    DartCompilerMainContext context = new DartCompilerMainContext(lib, provider, listener, config);
    Compiler compiler = new SelectiveCompiler(lib, selectiveCache, config, context);

    LibraryUnit topLibUnit = compiler.updateAndResolve();
    if (topLibUnit == null) {
      return null;
    }

    Map<URI, LibraryUnit> librariesToResolve;
    librariesToResolve = new HashMap<URI, LibraryUnit>();
    if (resolveAllNewLibs) {
      librariesToResolve.putAll(compiler.getLibraries());
    }
    librariesToResolve.put(topLibUnit.getSource().getUri(), topLibUnit);
    
    DartCompilationPhase[] phases = {
        new Resolver.Phase(),
        new CompileTimeConstantAnalyzer.Phase(),
        new TypeAnalyzer()};
    Map<URI, LibraryUnit> newLibraries = Maps.newHashMap();
    for (Entry<URI, LibraryUnit> entry : librariesToResolve.entrySet()) {
      URI libUri = entry.getKey();
      LibraryUnit libUnit = entry.getValue();
      if (!resolvedLibs.containsKey(libUri) && libUnit != null) {
        newLibraries.put(libUri, libUnit);
        for (DartCompilationPhase phase : phases) {
          // Run phase on all units, because "const" phase expects to have fully resolved library.
          for (DartUnit unit : libUnit.getUnits()) {
            if (unit.isDiet()) {
              continue;
            }
            unit = phase.exec(unit, context, compiler.getTypeProvider());
          }
        }
        // To help support the IDE, notify the listener that these unit were compiled.
        for (DartUnit unit : libUnit.getUnits()) {
          context.unitCompiled(unit);
        }
      }
    }

    return newLibraries;
  }

  /**
   * Re-analyzes source code after a modification. The modification is described by a SourceDelta.
   *
   * @param delta what has changed
   * @param enclosingLibrary the library in which the change occurred
   * @param interestStart beginning of interest area (as character offset from the beginning of the
   *          source file after the change.
   * @param interestLength length of interest area
   * @return a node which covers the entire interest area.
   */
  public static DartNode analyzeDelta(SourceDelta delta,
                                      LibraryElement enclosingLibrary,
                                      LibraryElement coreLibrary,
                                      DartNode interestNode,
                                      int interestStart,
                                      int interestLength,
                                      CompilerConfiguration config,
                                      DartCompilerListener listener) throws IOException {
    DeltaAnalyzer analyzer = new DeltaAnalyzer(delta, enclosingLibrary, coreLibrary,
                                               interestNode, interestStart, interestLength,
                                               config, listener);
    return analyzer.analyze();
  }

  public static LibraryUnit findLibrary(LibraryUnit libraryUnit, String uri,
      Set<LibraryElement> seen) {
    if (seen.contains(libraryUnit.getElement())) {
      return null;
    }
    seen.add(libraryUnit.getElement());
    if (uri.equals(libraryUnit.getName())) {
      return libraryUnit;
    }
    for (LibraryNode src : libraryUnit.getSourcePaths()) {
      if (src.getText().equals(uri)) {
        return libraryUnit;
      }
    }
    for (LibraryUnit importedLibrary : libraryUnit.getImportedLibraries()) {
      LibraryUnit unit = findLibrary(importedLibrary, uri, seen);
      if (unit != null) {
        return unit;
      }
    }
    return null;
  }

  public static LibraryUnit getCoreLib(LibraryUnit libraryUnit) {
    return findLibrary(libraryUnit, "dart:core", new HashSet<LibraryElement>());
  }

  private static void showVersion(CompilerOptions options) {
    String version = getSdkVersion(options);
    if (version == null) {
      version = "<unkown>";
    }
    System.out.println("dart_analyzer version " + version);
  }

  /**
   * @return the numeric revision of SDK, may be <code>null</code> if cannot find.
   */
  private static String getSdkVersion(CompilerOptions options) {
    try {
      File sdkPath = options.getDartSdkPath();
      File revisionFile = new File(sdkPath, "version");
      if (revisionFile.exists() && revisionFile.isFile()) {
        BufferedReader br = new BufferedReader(new FileReader(revisionFile));
        try {
          return br.readLine();
        } finally {
          br.close();
        }
      }
    } catch (Throwable e) {
    }
    return null;
  }
}
