// Copyright (c) 2015, 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.

library dart2js.parser.partial_elements;

import '../common/resolution.dart' show
    Parsing,
    Resolution;
import '../dart_types.dart' show DynamicType;
import '../diagnostics/diagnostic_listener.dart' show
    DiagnosticReporter;
import '../diagnostics/invariant.dart' show
    invariant;
import '../diagnostics/messages.dart';
import '../elements/elements.dart' show
    CompilationUnitElement,
    ConstructorElement,
    Element,
    ElementKind,
    GetterElement,
    LibraryElement,
    MetadataAnnotation,
    MethodElement,
    SetterElement,
    STATE_NOT_STARTED,
    STATE_DONE;
import '../elements/modelx.dart' show
    BaseFunctionElementX,
    ClassElementX,
    ConstructorElementX,
    DeclarationSite,
    ElementX,
    FieldElementX,
    GetterElementX,
    MetadataAnnotationX,
    MethodElementX,
    SetterElementX,
    TypedefElementX,
    VariableList;
import '../elements/visitor.dart' show
    ElementVisitor;
import '../tokens/token.dart' show
    BadInputToken,
    BeginGroupToken,
    ErrorToken,
    KeywordToken,
    StringToken,
    Token,
    UnmatchedToken,
    UnterminatedToken;
import '../tokens/token_constants.dart' as Tokens show
    EOF_TOKEN;
import '../tree/tree.dart';

import 'class_element_parser.dart' show
    ClassElementParser;
import 'parser.dart' show
    Parser;
import 'listener.dart' show
    ParserError;
import 'member_listener.dart' show
    MemberListener;
import 'node_listener.dart' show
    NodeListener;

abstract class PartialElement implements DeclarationSite {
  Token beginToken;
  Token endToken;

  bool hasParseError = false;

  bool get isErroneous => hasParseError;

  DeclarationSite get declarationSite => this;
}

abstract class PartialFunctionMixin implements BaseFunctionElementX {
  FunctionExpression cachedNode;
  Modifiers get modifiers;
  Token beginToken;
  Token getOrSet;
  Token endToken;

  /**
   * The position is computed in the constructor using [findMyName]. Computing
   * it on demand fails in case tokens are GC'd.
   */
  Token _position;

  void init(Token beginToken, Token getOrSet, Token endToken) {
    this.beginToken = beginToken;
    this.getOrSet = getOrSet;
    this.endToken = endToken;
    _position = ElementX.findNameToken(
        beginToken,
        modifiers.isFactory || isGenerativeConstructor,
        name, enclosingElement.name);
  }

  bool get hasNode => cachedNode != null;

  FunctionExpression get node {
    assert(invariant(this, cachedNode != null,
        message: "Node has not been computed for $this."));
    return cachedNode;
  }

  FunctionExpression parseNode(Parsing parsing) {
    if (cachedNode != null) return cachedNode;
    parseFunction(Parser p) {
      if (isClassMember && modifiers.isFactory) {
        p.parseFactoryMethod(beginToken);
      } else {
        p.parseFunction(beginToken, getOrSet);
      }
    }
    cachedNode = parse(parsing, this, declarationSite, parseFunction);
    return cachedNode;
  }

  Token get position => _position;

  void reusePartialFunctionMixin() {
    cachedNode = null;
  }

  DeclarationSite get declarationSite;
}

abstract class PartialFunctionElement
    implements PartialElement, PartialFunctionMixin {

  factory PartialFunctionElement(
      String name,
      Token beginToken,
      Token getOrSet,
      Token endToken,
      Modifiers modifiers,
      Element enclosingElement,
      {bool hasBody: true}) {
    if (getOrSet == null) {
      return new PartialMethodElement(
          name, beginToken, endToken, modifiers,
          enclosingElement, hasBody: hasBody);
    } else if (identical(getOrSet.stringValue, 'get')) {
      return new PartialGetterElement(
          name, beginToken, getOrSet, endToken, modifiers,
          enclosingElement, hasBody: hasBody);
    } else {
      assert(identical(getOrSet.stringValue, 'set'));
      return new PartialSetterElement(
          name, beginToken, getOrSet, endToken, modifiers,
          enclosingElement, hasBody: hasBody);
    }
  }

  PartialFunctionElement copyWithEnclosing(Element enclosing);
}


class PartialMethodElement extends MethodElementX
    with PartialElement, PartialFunctionMixin
    implements PartialFunctionElement {
  PartialMethodElement(String name,
                       Token beginToken,
                       Token endToken,
                       Modifiers modifiers,
                       Element enclosing,
                       {bool hasBody: true})
      : super(name, ElementKind.FUNCTION, modifiers, enclosing, hasBody) {
    init(beginToken, null, endToken);
  }

  void reuseElement() {
    super.reuseElement();
    reusePartialFunctionMixin();
  }

  PartialMethodElement copyWithEnclosing(Element enclosing) {
    return new PartialMethodElement(
        name, beginToken, endToken, modifiers, enclosing, hasBody: hasBody);
  }
}

class PartialGetterElement extends GetterElementX
    with PartialElement, PartialFunctionMixin
    implements GetterElement, PartialFunctionElement  {
  PartialGetterElement(String name,
                       Token beginToken,
                       Token getToken,
                       Token endToken,
                       Modifiers modifiers,
                       Element enclosing,
                       {bool hasBody: true})
      : super(name, modifiers, enclosing, hasBody) {
    init(beginToken, getToken, endToken);
  }

  @override
  SetterElement get setter => abstractField.setter;

  void reuseElement() {
    super.reuseElement();
    reusePartialFunctionMixin();
  }

  PartialGetterElement copyWithEnclosing(Element enclosing) {
    return new PartialGetterElement(
        name, beginToken, getOrSet, endToken, modifiers, enclosing,
        hasBody: hasBody);
  }
}

class PartialSetterElement extends SetterElementX
    with PartialElement, PartialFunctionMixin
    implements SetterElement, PartialFunctionElement {
  PartialSetterElement(String name,
                       Token beginToken,
                       Token setToken,
                       Token endToken,
                       Modifiers modifiers,
                       Element enclosing,
                       {bool hasBody: true})
      : super(name, modifiers, enclosing, hasBody) {
    init(beginToken, setToken, endToken);
  }

  @override
  GetterElement get getter => abstractField.getter;

  void reuseElement() {
    super.reuseElement();
    reusePartialFunctionMixin();
  }

  PartialSetterElement copyWithEnclosing(Element enclosing) {
    return new PartialSetterElement(
        name, beginToken, getOrSet, endToken, modifiers, enclosing,
        hasBody: hasBody);
  }
}

class PartialConstructorElement extends ConstructorElementX
    with PartialElement, PartialFunctionMixin {
  PartialConstructorElement(String name,
                            Token beginToken,
                            Token endToken,
                            ElementKind kind,
                            Modifiers modifiers,
                            Element enclosing)
      : super(name, kind, modifiers, enclosing) {
    init(beginToken, null, endToken);
  }

  void reuseElement() {
    super.reuseElement();
    reusePartialFunctionMixin();
  }
}

class PartialFieldList extends VariableList with PartialElement {
  PartialFieldList(Token beginToken,
                   Token endToken,
                   Modifiers modifiers,
                   bool hasParseError)
      : super(modifiers) {
    super.beginToken = beginToken;
    super.endToken = endToken;
    super.hasParseError = hasParseError;
  }

  VariableDefinitions parseNode(Element element, Parsing parsing) {
    if (definitions != null) return definitions;
    DiagnosticReporter reporter = parsing.reporter;
    reporter.withCurrentElement(element, () {
      definitions = parse(
          parsing, element, declarationSite,
          (Parser parser) => parser.parseMember(beginToken));

      if (!hasParseError &&
          !definitions.modifiers.isVar &&
          !definitions.modifiers.isFinal &&
          !definitions.modifiers.isConst &&
          definitions.type == null &&
          !definitions.isErroneous) {
        reporter.reportErrorMessage(
            definitions,
            MessageKind.GENERIC,
            { 'text': 'A field declaration must start with var, final, '
                      'const, or a type annotation.' });
      }
    });
    return definitions;
  }

  computeType(Element element, Resolution resolution) {
    if (type != null) return type;
    // TODO(johnniwinther): Compute this in the resolver.
    VariableDefinitions node = parseNode(element, resolution.parsing);
    if (node.type != null) {
      type = resolution.resolveTypeAnnotation(element, node.type);
    } else {
      type = const DynamicType();
    }
    assert(type != null);
    return type;
  }
}

class PartialTypedefElement extends TypedefElementX with PartialElement {

  PartialTypedefElement(
      String name,
      Element enclosing,
      Token beginToken,
      Token endToken)
      : super(name, enclosing) {
    this.beginToken = beginToken;
    this.endToken = endToken;
  }

  Token get token => beginToken;

  Node parseNode(Parsing parsing) {
    if (cachedNode != null) return cachedNode;
    cachedNode = parse(
        parsing, this, declarationSite,
        (p) => p.parseTopLevelDeclaration(token));
    return cachedNode;
  }

  Token get position => findMyName(token);
}

/// A [MetadataAnnotation] which is constructed on demand.
class PartialMetadataAnnotation extends MetadataAnnotationX
    implements PartialElement {
  Token beginToken; // TODO(ahe): Make this final when issue 22065 is fixed.

  final Token tokenAfterEndToken;

  Expression cachedNode;

  bool hasParseError = false;

  PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken);

  bool get isErroneous => hasParseError;

  DeclarationSite get declarationSite => this;

  Token get endToken {
    Token token = beginToken;
    while (token.kind != Tokens.EOF_TOKEN) {
      if (identical(token.next, tokenAfterEndToken)) break;
      token = token.next;
    }
    assert(token != null);
    return token;
  }

  void set endToken(_) {
    throw new UnsupportedError("endToken=");
  }

  Node parseNode(Parsing parsing) {
    if (cachedNode != null) return cachedNode;
    var metadata = parse(parsing,
                         annotatedElement,
                         declarationSite,
                         (p) => p.parseMetadata(beginToken));
    if (metadata is Metadata) {
      cachedNode = metadata.expression;
      return cachedNode;
    } else {
      assert (metadata is ErrorNode);
      return metadata;
    }
  }

  bool get hasNode => cachedNode != null;

  Node get node {
    assert(invariant(this, hasNode));
    return cachedNode;
  }
}

class PartialClassElement extends ClassElementX with PartialElement {
  ClassNode cachedNode;

  PartialClassElement(String name,
                      Token beginToken,
                      Token endToken,
                      Element enclosing,
                      int id)
      : super(name, enclosing, id, STATE_NOT_STARTED) {
    this.beginToken = beginToken;
    this.endToken = endToken;
  }

  void set supertypeLoadState(int state) {
    assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1);
    assert(state <= STATE_DONE);
    super.supertypeLoadState = state;
  }

  void set resolutionState(int state) {
    assert(state == STATE_NOT_STARTED || state == resolutionState + 1);
    assert(state <= STATE_DONE);
    super.resolutionState = state;
  }

  bool get hasNode => cachedNode != null;

  ClassNode get node {
    assert(invariant(this, cachedNode != null,
        message: "Node has not been computed for $this."));
    return cachedNode;
  }

  ClassNode parseNode(Parsing parsing) {
    if (cachedNode != null) return cachedNode;
    DiagnosticReporter reporter = parsing.reporter;
    reporter.withCurrentElement(this, () {
      parsing.measure(() {
        MemberListener listener = new MemberListener(reporter, this);
        Parser parser = new ClassElementParser(listener);
        try {
          Token token = parser.parseTopLevelDeclaration(beginToken);
          assert(identical(token, endToken.next));
          cachedNode = listener.popNode();
          assert(
              invariant(
                  beginToken, listener.nodes.isEmpty,
                  message: "Non-empty listener stack: ${listener.nodes}"));
        } on ParserError {
          // TODO(ahe): Often, a ParserError is thrown while parsing the class
          // body. This means that the stack actually contains most of the
          // information synthesized below. Consider rewriting the parser so
          // endClassDeclaration is called before parsing the class body.
          Identifier name = new Identifier(findMyName(beginToken));
          NodeList typeParameters = null;
          Node supertype = null;
          NodeList interfaces = listener.makeNodeList(0, null, null, ",");
          Token extendsKeyword = null;
          NodeList body = listener.makeNodeList(0, beginToken, endToken, null);
          cachedNode = new ClassNode(
              Modifiers.EMPTY, name, typeParameters, supertype, interfaces,
              beginToken, extendsKeyword, body, endToken);
          hasParseError = true;
        }
      });
      if (isPatched) {
        parsing.parsePatchClass(patch);
      }
    });
    return cachedNode;
  }

  Token get position => beginToken;

  // TODO(johnniwinther): Ensure that modifiers are always available.
  Modifiers get modifiers =>
      cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;

  accept(ElementVisitor visitor, arg) {
    return visitor.visitClassElement(this, arg);
  }

  PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) {
    return new PartialClassElement(name, beginToken, endToken, enclosing, id);
  }
}

Node parse(
    Parsing parsing,
    ElementX element,
    PartialElement partial,
    doParse(Parser parser)) {
  DiagnosticReporter reporter = parsing.reporter;
  return parsing.measure(() {
    return reporter.withCurrentElement(element, () {
      CompilationUnitElement unit = element.compilationUnit;
      NodeListener listener = new NodeListener(reporter, unit);
      listener.memberErrors = listener.memberErrors.prepend(false);
      try {
        if (partial.hasParseError) {
          listener.suppressParseErrors = true;
        }
        doParse(new Parser(listener));
      } on ParserError catch (e) {
        partial.hasParseError = true;
        return new ErrorNode(element.position, e.reason);
      }
      Node node = listener.popNode();
      assert(listener.nodes.isEmpty);
      return node;
    });
  });
}
