// 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.dart';
import '../common/resolution.dart' show ParsingContext, Resolution;
import '../dart_types.dart' show DynamicType;
import '../elements/elements.dart'
    show
        CompilationUnitElement,
        Element,
        ElementKind,
        GetterElement,
        MetadataAnnotation,
        SetterElement,
        STATE_NOT_STARTED,
        STATE_DONE;
import '../elements/modelx.dart'
    show
        BaseFunctionElementX,
        ClassElementX,
        ConstructorElementX,
        DeclarationSite,
        ElementX,
        GetterElementX,
        MetadataAnnotationX,
        MethodElementX,
        SetterElementX,
        TypedefElementX,
        VariableList;
import '../elements/visitor.dart' show ElementVisitor;
import '../tokens/token.dart' show Token;
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
import '../tree/tree.dart';
import 'class_element_parser.dart' show ClassElementParser;
import 'listener.dart' show ParserError;
import 'member_listener.dart' show MemberListener;
import 'node_listener.dart' show NodeListener;
import 'parser.dart' show Parser;

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

  bool hasParseError = false;

  bool get isMalformed => 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(ParsingContext 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);
  }
}

// TODO(johnniwinther): Create [PartialGenerativeConstructor] and
// [PartialFactoryConstructor] subclasses and make this abstract.
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, ParsingContext 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.parsingContext);
    if (node.type != null) {
      type = resolution.reporter.withCurrentElement(element, () {
        return 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(ParsingContext 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 isMalformed => 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(ParsingContext 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(ParsingContext parsing) {
    if (cachedNode != null) return cachedNode;
    DiagnosticReporter reporter = parsing.reporter;
    reporter.withCurrentElement(this, () {
      parsing.measure(() {
        MemberListener listener = new MemberListener(
            parsing.getScannerOptionsFor(this), 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(ParsingContext 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(
          parsing.getScannerOptionsFor(element), 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;
    });
  });
}
