// 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/sdk_library_metadata/lib/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 dart2js.patchparser;

import 'dart:async';

import 'package:front_end/src/fasta/parser.dart'
    show Listener, Parser, ParserError;
import 'package:front_end/src/fasta/scanner.dart' show Token;

import 'common/tasks.dart' show CompilerTask;
import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constants/values.dart' show ConstantValue;
import 'elements/resolution_types.dart' show ResolutionDartType;
import 'elements/elements.dart';
import 'elements/modelx.dart'
    show
        BaseFunctionElementX,
        ClassElementX,
        GetterElementX,
        LibraryElementX,
        MetadataAnnotationX,
        SetterElementX;
import 'elements/names.dart';
import 'enqueue.dart' show DeferredAction;
import 'id_generator.dart';
import 'library_loader.dart' show LibraryLoader;
import 'parser/element_listener.dart' show ElementListener;
import 'parser/member_listener.dart' show MemberListener;
import 'parser/partial_elements.dart'
    show ClassElementParser, PartialClassElement;
import 'parser/diet_parser_task.dart' show PartialParser;
import 'script.dart';

class PatchParserTask extends CompilerTask {
  final String name = "Patching Parser";
  final Compiler compiler;
  DiagnosticReporter get reporter => compiler.reporter;

  PatchParserTask(Compiler compiler)
      : compiler = compiler,
        super(compiler.measurer);

  /**
   * Scans a library patch file, applies the method patches and
   * injections to the library, and returns a list of class
   * patches.
   */
  Future patchLibrary(
      LibraryLoader loader, Uri patchUri, LibraryElement originLibrary) {
    return compiler.readScript(patchUri, originLibrary).then((Script script) {
      var patchLibrary = new LibraryElementX(script, null, originLibrary);
      return reporter.withCurrentElement(patchLibrary, () {
        loader.registerNewLibrary(patchLibrary);
        reporter.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);
        });
        return loader.processLibraryTags(patchLibrary);
      });
    });
  }

  void scanLibraryElements(CompilationUnitElement compilationUnit) {
    measure(() {
      // TODO(johnniwinther): Test that parts and exports are handled correctly.
      Script script = compilationUnit.script;
      Token tokens = compiler.scanner.scanFile(script.file);
      Listener patchListener = new PatchElementListener(
          compiler, compilationUnit, compiler.idGenerator);
      try {
        new PartialParser(patchListener).parseUnit(tokens);
      } on ParserError catch (e) {
        // No need to recover from a parser error in platform libraries, user
        // will never see this if the libraries are tested correctly.
        reporter.internalError(
            compilationUnit, "Parser error in patch file: $e");
      }
    });
  }

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

    measure(() => reporter.withCurrentElement(cls, () {
          MemberListener listener = new PatchMemberListener(compiler, cls);
          Parser parser = new ClassElementParser(listener);
          try {
            Token token = parser.parseTopLevelDeclaration(cls.beginToken);
            assert(identical(token, cls.endToken.next));
          } on ParserError catch (e) {
            // No need to recover from a parser error in platform libraries,
            // user will never see this if the libraries are tested correctly.
            reporter.internalError(cls, "Parser error in patch file: $e");
          }
          cls.cachedNode = listener.popNode();
          assert(listener.nodes.isEmpty);
        }));
  }
}

class PatchMemberListener extends MemberListener {
  final Compiler compiler;

  PatchMemberListener(Compiler compiler, ClassElement enclosingClass)
      : this.compiler = compiler,
        super(compiler.parsingContext.getScannerOptionsFor(enclosingClass),
            compiler.reporter, enclosingClass);

  @override
  void addMember(Element patch) {
    addMetadata(patch);

    if (_isMarkedAsPatch(compiler, patch)) {
      Element origin = enclosingClass.origin.localLookup(patch.name);
      patchElement(compiler, reporter, origin, patch);
      enclosingClass.addMember(patch, reporter);
    } else {
      if (Name.isPublicName(patch.name)) {
        reporter.reportErrorMessage(patch, MessageKind.INJECTED_PUBLIC_MEMBER);
      }
      enclosingClass.addMember(patch, reporter);
    }
  }
}

/**
 * Extension of [ElementListener] for parsing patch files.
 */
class PatchElementListener extends ElementListener implements Listener {
  final Compiler compiler;

  PatchElementListener(Compiler compiler, CompilationUnitElement patchElement,
      IdGenerator idGenerator)
      : this.compiler = compiler,
        super(compiler.parsingContext.getScannerOptionsFor(patchElement),
            compiler.reporter, patchElement, idGenerator);

  @override
  void pushElement(Element patch) {
    popMetadata(patch);

    if (_isMarkedAsPatch(compiler, patch)) {
      LibraryElement originLibrary = compilationUnitElement.library;
      assert(originLibrary.isPatched);
      Element origin = originLibrary.localLookup(patch.name);
      patchElement(compiler, reporter, origin, patch);
      compilationUnitElement.addMember(patch, reporter);
    } else {
      if (Name.isPublicName(patch.name)) {
        reporter.reportErrorMessage(patch, MessageKind.INJECTED_PUBLIC_MEMBER);
      }
      compilationUnitElement.addMember(patch, reporter);
    }
  }
}

void patchElement(Compiler compiler, DiagnosticReporter reporter,
    Element origin, Element patch) {
  if (origin == null) {
    reporter.reportErrorMessage(
        patch, MessageKind.PATCH_NON_EXISTING, {'name': patch.name});
    return;
  }

  if (!(origin.isClass ||
      origin.isConstructor ||
      origin.isFunction ||
      origin.isAbstractField)) {
    // TODO(ahe): Remove this error when the parser rejects all bad modifiers.
    reporter.reportErrorMessage(origin, MessageKind.PATCH_NONPATCHABLE);
    return;
  }
  if (patch.isClass) {
    tryPatchClass(compiler, reporter, origin, patch);
  } else if (patch.isGetter) {
    tryPatchGetter(reporter, origin, patch);
  } else if (patch.isSetter) {
    tryPatchSetter(reporter, origin, patch);
  } else if (patch.isConstructor) {
    tryPatchConstructor(reporter, origin, patch);
  } else if (patch.isFunction) {
    tryPatchFunction(reporter, origin, patch);
  } else {
    // TODO(ahe): Remove this error when the parser rejects all bad modifiers.
    reporter.reportErrorMessage(patch, MessageKind.PATCH_NONPATCHABLE);
  }
}

void tryPatchClass(Compiler compiler, DiagnosticReporter reporter,
    Element origin, ClassElement patch) {
  if (!origin.isClass) {
    reporter.reportError(
        reporter.createMessage(
            origin, MessageKind.PATCH_NON_CLASS, {'className': patch.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_CLASS,
              {'className': patch.name}),
        ]);
    return;
  }
  patchClass(compiler, reporter, origin, patch);
}

void patchClass(Compiler compiler, DiagnosticReporter reporter,
    ClassElementX origin, ClassElementX patch) {
  if (origin.isPatched) {
    reporter.internalError(origin, "Patching the same class more than once.");
  }
  origin.applyPatch(patch);
}

/// Abstract interface for pre-resolution detection of metadata.
///
/// The detection is handled in two steps:
/// - match the annotation syntactically and assume that the annotation is valid
///   if it looks correct,
/// - setup a deferred action to check that the annotation has a valid constant
///   value and report an internal error if not.
abstract class EagerAnnotationHandler<T> {
  const EagerAnnotationHandler();

  /// Checks that [annotation] looks like a matching annotation and optionally
  /// applies actions on [element]. Returns a non-null annotation marker if the
  /// annotation matched and should be validated.
  T apply(Compiler compiler, Element element, MetadataAnnotation annotation);

  /// Checks that the annotation value is valid.
  void validate(Compiler compiler, Element element,
      MetadataAnnotation annotation, ConstantValue constant);

  /// Checks [element] for metadata matching the [handler]. Return a non-null
  /// annotation marker matching metadata was found.
  static T checkAnnotation<T>(
      Compiler compiler, Element element, EagerAnnotationHandler<T> handler) {
    for (MetadataAnnotation annotation in element.implementation.metadata) {
      T result = handler.apply(compiler, element, annotation);
      if (result != handler.defaultResult) {
        // TODO(johnniwinther): Perform this check in
        // [Compiler.processLoadedLibraries].
        compiler.libraryLoader
            .registerDeferredAction(new DeferredAction(element, () {
          annotation.ensureResolved(compiler.resolution);
          handler.validate(compiler, element, annotation,
              compiler.constants.getConstantValue(annotation.constant));
        }));
        return result;
      }
    }
    return handler.defaultResult;
  }

  /// Result that signals the absence of annotations.
  T get defaultResult => null;
}

/// Annotation handler for pre-resolution detection of `@patch` annotations.
class PatchAnnotationHandler extends EagerAnnotationHandler<bool> {
  const PatchAnnotationHandler();

  @override
  bool apply(
      Compiler compiler, Element element, MetadataAnnotation annotation) {
    MetadataAnnotationX meta = annotation;
    if (meta.beginToken?.next?.lexeme == 'patch') {
      return true;
    }
    return null;
  }

  @override
  void validate(Compiler compiler, Element element,
      MetadataAnnotation annotation, ConstantValue constant) {
    ResolutionDartType annotationType =
        constant.getType(compiler.resolution.commonElements);
    if (annotationType.element !=
        compiler.resolution.commonElements.patchAnnotationClass) {
      DiagnosticReporter reporter = compiler.reporter;
      reporter.internalError(annotation, 'Invalid patch annotation.');
    }
  }
}

void tryPatchGetter(
    DiagnosticReporter reporter, Element origin, FunctionElement patch) {
  if (!origin.isAbstractField) {
    reporter.reportError(
        reporter.createMessage(
            origin, MessageKind.PATCH_NON_GETTER, {'name': origin.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_GETTER,
              {'getterName': patch.name}),
        ]);
    return;
  }
  AbstractFieldElement originField = origin;
  if (originField.getter == null) {
    reporter.reportError(
        reporter.createMessage(
            origin, MessageKind.PATCH_NO_GETTER, {'getterName': patch.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_GETTER,
              {'getterName': patch.name}),
        ]);
    return;
  }
  GetterElementX getter = originField.getter;
  patchFunction(reporter, getter, patch);
}

void tryPatchSetter(
    DiagnosticReporter reporter, Element origin, FunctionElement patch) {
  if (!origin.isAbstractField) {
    reporter.reportError(
        reporter.createMessage(
            origin, MessageKind.PATCH_NON_SETTER, {'name': origin.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_SETTER,
              {'setterName': patch.name}),
        ]);
    return;
  }
  AbstractFieldElement originField = origin;
  if (originField.setter == null) {
    reporter.reportError(
        reporter.createMessage(
            origin, MessageKind.PATCH_NO_SETTER, {'setterName': patch.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_SETTER,
              {'setterName': patch.name}),
        ]);
    return;
  }
  SetterElementX setter = originField.setter;
  patchFunction(reporter, setter, patch);
}

void tryPatchConstructor(
    DiagnosticReporter reporter, Element origin, FunctionElement patch) {
  if (!origin.isConstructor) {
    reporter.reportError(
        reporter.createMessage(origin, MessageKind.PATCH_NON_CONSTRUCTOR,
            {'constructorName': patch.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_CONSTRUCTOR,
              {'constructorName': patch.name}),
        ]);
    return;
  }
  patchFunction(reporter, origin, patch);
}

void tryPatchFunction(
    DiagnosticReporter reporter, Element origin, FunctionElement patch) {
  if (!origin.isFunction) {
    reporter.reportError(
        reporter.createMessage(origin, MessageKind.PATCH_NON_FUNCTION,
            {'functionName': patch.name}),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_FUNCTION,
              {'functionName': patch.name}),
        ]);
    return;
  }
  patchFunction(reporter, origin, patch);
}

void patchFunction(DiagnosticReporter reporter, BaseFunctionElementX origin,
    BaseFunctionElementX patch) {
  if (!origin.modifiers.isExternal) {
    reporter.reportError(
        reporter.createMessage(origin, MessageKind.PATCH_NON_EXTERNAL),
        <DiagnosticMessage>[
          reporter.createMessage(patch, MessageKind.PATCH_POINT_TO_FUNCTION,
              {'functionName': patch.name}),
        ]);
    return;
  }
  if (origin.isPatched) {
    reporter.internalError(
        origin, "Trying to patch a function more than once.");
  }
  origin.applyPatch(patch);
}

bool _isMarkedAsPatch(Compiler compiler, Element element) {
  return EagerAnnotationHandler.checkAnnotation(
          compiler, element, const PatchAnnotationHandler()) ==
      true;
}
