// 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.

/**
 * This library contains the infrastructure to parse and integrate patch files.
 *
 * Three types of elements can be patched: [LibraryElement], [ClassElement],
 * [FunctionElement]. Patches are introduced in patch libraries which are loaded
 * together with the corresponding origin library. Which libraries that are
 * patched is determined by the dart2jsPatchPath field of LibraryInfo found
 * in [:lib/_internal/libraries.dart:].
 *
 * Patch libraries are parsed like regular library and thus provided with their
 * own elements. These elements which are distinct from the elements from the
 * patched library and the relation between patched and patch elements is
 * established through the [:patch:] and [:origin:] fields found on
 * [LibraryElement], [ClassElement] and [FunctionElement]. The [:patch:] fields
 * are set on the patched elements to point to their corresponding patch
 * element, and the [:origin:] elements are set on the patch elements to point
 * their corresponding patched elements.
 *
 * The fields [Element.isPatched] and [Element.isPatch] can be used to determine
 * whether the [:patch:] or [:origin:] field, respectively, has been set on an
 * element, regardless of whether the element is one of the three patchable
 * element types or not.
 *
 * ## Variants of Classes and Functions ##
 *
 * With patches there are four variants of classes and function:
 *
 * Regular: A class or function which is not declared in a patch library and
 *   which has no corresponding patch.
 * Origin: A class or function which is not declared in a patch library and
 *   which has a corresponding patch. Origin functions must use the [:external:]
 *   modifier and can have no body. Origin classes and functions are also
 *   called 'patched'.
 * Patch: A class or function which is declared in a patch library and which
 *   has a corresponding origin. Both patch classes and patch functions must use
 *   the [:patch:] modifier.
 * Injected: A class or function (or even field) which is declared in a
 *   patch library and which has no corresponding origin. An injected element
 *   cannot use the [:patch:] modifier. Injected elements are never visible from
 *   outside the patch library in which they have been declared. For this
 *   reason, injected elements are often declared private and therefore called
 *   also called 'patch private'.
 *
 * Examples of the variants is shown in the code below:
 *
 *     // In the origin library:
 *     class RegularClass { // A regular class.
 *       void regularMethod() {} // A regular method.
 *     }
 *     class PatchedClass { // An origin class.
 *       int regularField; // A regular field.
 *       void regularMethod() {} // A regular method.
 *       external void patchedMethod(); // An origin method.
 *     }
 *
 *     // In the patch library:
 *     class _InjectedClass { // An injected class.
 *       void _injectedMethod() {} // An injected method.
 *     }
 *     patch class PatchedClass { // A patch class.
 *       int _injectedField; { // An injected field.
 *       patch void patchedMethod() {} // A patch method.
 *     }
 *
 *
 * ## Declaration and Implementation ##
 *
 * With patches we have two views on elements: as the 'declaration' which
 * introduces the entity and defines its interface, and as the 'implementation'
 * which defines the actual implementation of the entity.
 *
 * Every element has a 'declaration' and an 'implementation' element. For
 * regular and injected elements these are the same. For origin elements the
 * declaration is the element itself and the implementation is the patch element
 * found through its [:patch:] field. For patch elements the implementation is
 * the element itself and the declaration is the origin element found through
 * its [:origin:] field. The declaration and implementation of any element is
 * conveniently available through the [Element.declaration] and
 * [Element.implementation] getters.
 *
 * Most patch-related invariants enforced through-out the compiler are defined
 * in terms of 'declaration' and 'implementation', and tested through the
 * predicate getters [Element.isDeclaration] and [Element.isImplementation].
 * Patch invariants are stated both in comments and as assertions.
 *
 *
 * ## General invariant guidelines ##
 *
 * For [LibraryElement] we always use declarations. This means the
 * [Element.getLibrary] method will only return library declarations. Patch
 * library implementations are only accessed through calls to
 * [Element.getImplementationLibrary] which is used to setup the correct
 * [Element.enclosingElement] relation between patch/injected elements and the
 * patch library.
 *
 * For [ClassElement] and [FunctionElement] we use declarations for determining
 * identity and implementations for work based on the AST nodes, such as
 * resolution, type-checking, type inference, building SSA graphs, etc.
 * - Worklist only contain declaration elements.
 * - Most maps and sets use declarations exclusively, and their individual
 *   invariants are stated in the field comments.
 * - [tree.TreeElements] only map to patch elements from inside a patch library.
 *   TODO(johnniwinther): Simplify this invariant to use only declarations in
 *   [tree.TreeElements].
 * - Builders shift between declaration and implementation depending on usages.
 * - Compile-time constants use constructor implementation exclusively.
 * - Work on function parameters is performed on the declaration of the function
 *   element.
 */

library patchparser;

import "dart:uri";
import "tree/tree.dart" as tree;
import "dart2jslib.dart" as leg;  // CompilerTask, Compiler.
import "apiimpl.dart";
import "../compiler.dart" as api;
import "scanner/scannerlib.dart";  // Scanner, Parsers, Listeners
import "elements/elements.dart";
import "elements/modelx.dart" show LibraryElementX, MetadataAnnotationX;
import 'util/util.dart';

class PatchParserTask extends leg.CompilerTask {
  PatchParserTask(leg.Compiler compiler): super(compiler);
  final String name = "Patching Parser";

  /**
   * Scans a library patch file, applies the method patches and
   * injections to the library, and returns a list of class
   * patches.
   */
  void patchLibrary(leg.LibraryDependencyHandler handler,
                    Uri patchUri, LibraryElement originLibrary) {

    leg.Script script = compiler.readScript(patchUri, null);
    var patchLibrary = new LibraryElementX(script, null, originLibrary);
    compiler.withCurrentElement(patchLibrary, () {
      handler.registerNewLibrary(patchLibrary);
      LinkBuilder<tree.LibraryTag> imports = new LinkBuilder<tree.LibraryTag>();
      compiler.withCurrentElement(patchLibrary.entryCompilationUnit, () {
        // This patches the elements of the patch library into [library].
        // Injected elements are added directly under the compilation unit.
        // Patch elements are stored on the patched functions or classes.
        scanLibraryElements(patchLibrary.entryCompilationUnit, imports);
      });
      // After scanning declarations, we handle the import tags in the patch.
      // TODO(lrn): These imports end up in the original library and are in
      // scope for the original methods too. This should be fixed.
      compiler.importHelperLibrary(originLibrary);
      for (tree.LibraryTag tag in imports.toLink()) {
        compiler.libraryLoader.registerLibraryFromTag(
            handler, patchLibrary, tag);
      }
    });
  }

  void scanLibraryElements(
        CompilationUnitElement compilationUnit,
        LinkBuilder<tree.LibraryTag> imports) {
    measure(() {
      // TODO(lrn): Possibly recursively handle #source directives in patch.
      leg.Script script = compilationUnit.script;
      Token tokens = new StringScanner(script.text).tokenize();
      Function idGenerator = compiler.getNextFreeClassId;
      PatchListener patchListener =
          new PatchElementListener(compiler,
                                   compilationUnit,
                                   idGenerator,
                                   imports);
      new PatchParser(patchListener).parseUnit(tokens);
    });
  }

  void parsePatchClassNode(PartialClassElement element) {
    // Parse [PartialClassElement] using a "patch"-aware parser instead
    // of calling its [parseNode] method.
    if (element.cachedNode != null) return;

    return measure(() => compiler.withCurrentElement(element, () {
      PatchMemberListener listener = new PatchMemberListener(compiler, element);
      Parser parser = new PatchClassElementParser(listener);
      Token token = parser.parseTopLevelDeclaration(element.beginToken);
      assert(identical(token, element.endToken.next));
      element.cachedNode = listener.popNode();
      assert(listener.nodes.isEmpty);

      Link<Element> patches = element.localMembers;
      applyContainerPatch(element.origin, patches);
    }));
  }

  void applyContainerPatch(ClassElement originClass,
                           Link<Element> patches) {
    for (Element patch in patches) {
      if (!isPatchElement(patch)) continue;

      Element origin = originClass.localLookup(patch.name);
      patchElement(compiler, origin, patch);
    }
  }
}

/**
 * Extension of the [Listener] interface to handle the extra "patch" pseudo-
 * keyword in patch files.
 * Patch files shouldn't have a type named "patch".
 */
abstract class PatchListener extends Listener {
  void beginPatch(Token patch);
  void endPatch(Token patch);
}

/**
 * Partial parser that extends the top-level and class grammars to allow the
 * word "patch" in front of some declarations.
 */
class PatchParser extends PartialParser {
  PatchParser(PatchListener listener) : super(listener);

  PatchListener get patchListener => listener;

  bool isPatch(Token token) {
    return token.stringValue == null &&
           token.slowToString() == "patch";
  }

  /**
   * Parse top-level declarations, and allow "patch" in front of functions
   * and classes.
   */
  Token parseTopLevelDeclaration(Token token) {
    if (!isPatch(token)) {
      return super.parseTopLevelDeclaration(token);
    }
    Token patch = token;
    token = token.next;
    String value = token.stringValue;
    if (identical(value, 'interface')
        || identical(value, 'typedef')
        || identical(value, '#')
        || identical(value, 'abstract')) {
      // At the top level, you can only patch functions and classes.
      // Patch classes and functions can't be marked abstract.
      return listener.unexpected(patch);
    }
    patchListener.beginPatch(patch);
    token = super.parseTopLevelDeclaration(token);
    patchListener.endPatch(patch);
    return token;
  }

  /**
   * Parse a class member.
   * If the member starts with "patch", it's a member override.
   * Only methods can be overridden, including constructors, getters and
   * setters, but not fields. If "patch" occurs in front of a field, the error
   * is caught elsewhere.
   */
  Token parseMember(Token token) {
    if (!isPatch(token)) {
      return super.parseMember(token);
    }
    Token patch = token;
    patchListener.beginPatch(patch);
    token = super.parseMember(token.next);
    patchListener.endPatch(patch);
    return token;
  }
}

/**
 * Partial parser for patch files that also handles the members of class
 * declarations.
 */
class PatchClassElementParser extends PatchParser {
  PatchClassElementParser(PatchListener listener) : super(listener);

  Token parseClassBody(Token token) => fullParseClassBody(token);
}

/**
 * Extension of [ElementListener] for parsing patch files.
 */
class PatchElementListener extends ElementListener implements PatchListener {
  final LinkBuilder<tree.LibraryTag> imports;
  bool isMemberPatch = false;
  bool isClassPatch = false;

  PatchElementListener(leg.DiagnosticListener listener,
                       CompilationUnitElement patchElement,
                       int idGenerator(),
                       this.imports)
    : super(listener, patchElement, idGenerator);

  MetadataAnnotation popMetadataHack() {
    // TODO(ahe): Remove this method.
    popNode(); // Discard null.
    return new PatchMetadataAnnotation();
  }

  void beginPatch(Token token) {
    if (identical(token.next.stringValue, "class")) {
      isClassPatch = true;
    } else {
      isMemberPatch = true;
    }
    handleIdentifier(token);
  }

  void endPatch(Token token) {
    if (identical(token.next.stringValue, "class")) {
      isClassPatch = false;
    } else {
      isMemberPatch = false;
    }
  }

  /**
    * Allow script tags (import only, the parser rejects the rest for now) in
    * patch files. The import tags will be added to the library.
    */
  bool allowLibraryTags() => true;

  void addLibraryTag(tree.LibraryTag tag) {
    super.addLibraryTag(tag);
    imports.addLast(tag);
  }

  void pushElement(Element patch) {
    if (isMemberPatch || (isClassPatch && patch is ClassElement)) {
      // Apply patch.
      patch.addMetadata(popMetadataHack());
      LibraryElement originLibrary = compilationUnitElement.getLibrary();
      assert(originLibrary.isPatched);
      Element origin = originLibrary.localLookup(patch.name);
      patchElement(listener, origin, patch);
    }
    super.pushElement(patch);
  }
}

/**
 * Extension of [MemberListener] for parsing patch class bodies.
 */
class PatchMemberListener extends MemberListener implements PatchListener {
  bool isMemberPatch = false;
  bool isClassPatch = false;
  PatchMemberListener(leg.DiagnosticListener listener,
                      Element enclosingElement)
    : super(listener, enclosingElement);

  MetadataAnnotation popMetadataHack() {
    // TODO(ahe): Remove this method.
    popNode(); // Discard null.
    return new PatchMetadataAnnotation();
  }

  void beginPatch(Token token) {
    if (identical(token.next.stringValue, "class")) {
      isClassPatch = true;
    } else {
      isMemberPatch = true;
    }
    handleIdentifier(token);
  }

  void endPatch(Token token) {
    if (identical(token.next.stringValue, "class")) {
      isClassPatch = false;
    } else {
      isMemberPatch = false;
    }
  }

  void addMember(Element element) {
    if (isMemberPatch || (isClassPatch && element is ClassElement)) {
      element.addMetadata(popMetadataHack());
    }
    super.addMember(element);
  }
}

// TODO(ahe): Get rid of this class.
class PatchMetadataAnnotation extends MetadataAnnotationX {
  final leg.Constant value = null;

  PatchMetadataAnnotation() : super(STATE_DONE);

  Token get beginToken => null;
  Token get endToken => null;
}

void patchElement(leg.DiagnosticListener listener,
                   Element origin,
                   Element patch) {
  if (origin == null) {
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_NON_EXISTING.error({'name': patch.name}),
        api.Diagnostic.ERROR);
    return;
  }
  if (!(origin.isClass() ||
        origin.isConstructor() ||
        origin.isFunction() ||
        origin.isAbstractField())) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NONPATCHABLE.error(),
        api.Diagnostic.ERROR);
    return;
  }
  if (patch.isClass()) {
    tryPatchClass(listener, origin, patch);
  } else if (patch.isGetter()) {
    tryPatchGetter(listener, origin, patch);
  } else if (patch.isSetter()) {
    tryPatchSetter(listener, origin, patch);
  } else if (patch.isConstructor()) {
    tryPatchConstructor(listener, origin, patch);
  } else if(patch.isFunction()) {
    tryPatchFunction(listener, origin, patch);
  } else {
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_NONPATCHABLE.error(),
        api.Diagnostic.ERROR);
  }
}

void tryPatchClass(leg.DiagnosticListener listener,
                    Element origin,
                    ClassElement patch) {
  if (!origin.isClass()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_CLASS.error({'className': patch.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_CLASS.error({'className': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  patchClass(listener, origin, patch);
}

void patchClass(leg.DiagnosticListener listener,
                 ClassElement origin,
                 ClassElement patch) {
  if (origin.isPatched) {
    listener.internalErrorOnElement(
        origin, "Patching the same class more than once.");
  }
  // TODO(johnniwinther): Change to functions on the ElementX class.
  origin.patch = patch;
  patch.origin = origin;
}

void tryPatchGetter(leg.DiagnosticListener listener,
                     Element origin,
                     FunctionElement patch) {
  if (!origin.isAbstractField()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_GETTER.error({'name': origin.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_GETTER.error({'getterName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  AbstractFieldElement originField = origin;
  if (originField.getter == null) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NO_GETTER.error({'getterName': patch.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_GETTER.error({'getterName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  patchFunction(listener, originField.getter, patch);
}

void tryPatchSetter(leg.DiagnosticListener listener,
                     Element origin,
                     FunctionElement patch) {
  if (!origin.isAbstractField()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_SETTER.error({'name': origin.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_SETTER.error({'setterName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  AbstractFieldElement originField = origin;
  if (originField.setter == null) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NO_SETTER.error({'setterName': patch.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_SETTER.error({'setterName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  patchFunction(listener, originField.setter, patch);
}

void tryPatchConstructor(leg.DiagnosticListener listener,
                          Element origin,
                          FunctionElement patch) {
  if (!origin.isConstructor()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_CONSTRUCTOR.error(
            {'constructorName': patch.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_CONSTRUCTOR.error(
            {'constructorName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  patchFunction(listener, origin, patch);
}

void tryPatchFunction(leg.DiagnosticListener listener,
                       Element origin,
                       FunctionElement patch) {
  if (!origin.isFunction()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_FUNCTION.error({'functionName': patch.name}),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_FUNCTION.error(
            {'functionName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  patchFunction(listener, origin, patch);
}

void patchFunction(leg.DiagnosticListener listener,
                    FunctionElement origin,
                    FunctionElement patch) {
  if (!origin.modifiers.isExternal()) {
    listener.reportMessage(
        listener.spanFromSpannable(origin),
        leg.MessageKind.PATCH_NON_EXTERNAL.error(),
        api.Diagnostic.ERROR);
    listener.reportMessage(
        listener.spanFromSpannable(patch),
        leg.MessageKind.PATCH_POINT_TO_FUNCTION.error(
            {'functionName': patch.name}),
        api.Diagnostic.INFO);
    return;
  }
  if (origin.isPatched) {
    listener.internalErrorOnElement(origin,
        "Trying to patch a function more than once.");
  }
  if (origin.cachedNode != null) {
    listener.internalErrorOnElement(origin,
        "Trying to patch an already compiled function.");
  }
  // Don't just assign the patch field. This also updates the cachedNode.
  // TODO(johnniwinther): Change to functions on the ElementX class.
  origin.setPatch(patch);
  patch.origin = origin;
}

// TODO(johnniwinther): Add unittest when patch is (real) metadata.
bool isPatchElement(Element element) {
  // TODO(lrn): More checks needed if we introduce metadata for real.
  // In that case, it must have the identifier "native" as metadata.
  for (Link link = element.metadata; !link.isEmpty; link = link.tail) {
    if (link.head is PatchMetadataAnnotation) return true;
  }
  return false;
}
