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

import '../common.dart';
import '../elements/elements.dart'
    show Element, ElementKind, Elements, MetadataAnnotation;
import '../elements/modelx.dart'
    show ClassElementX, ElementX, FieldElementX, VariableList;
import '../tokens/token.dart' show Token;
import '../tree/tree.dart';

import 'element_listener.dart' show ScannerOptions;
import 'node_listener.dart' show NodeListener;
import 'partial_elements.dart'
    show
        PartialConstructorElement,
        PartialFunctionElement,
        PartialMetadataAnnotation;

class MemberListener extends NodeListener {
  final ClassElementX enclosingClass;

  MemberListener(ScannerOptions scannerOptions, DiagnosticReporter listener,
      ClassElementX enclosingElement)
      : this.enclosingClass = enclosingElement,
        super(scannerOptions, listener, enclosingElement.compilationUnit);

  bool isConstructorName(Node nameNode) {
    if (enclosingClass == null || enclosingClass.kind != ElementKind.CLASS) {
      return false;
    }
    String name;
    if (nameNode.asIdentifier() != null) {
      name = nameNode.asIdentifier().source;
    } else {
      Send send = nameNode.asSend();
      name = send.receiver.asIdentifier().source;
    }
    return enclosingClass.name == name;
  }

  // TODO(johnniwinther): Remove this method.
  String getMethodNameHack(Node methodName) {
    Send send = methodName.asSend();
    if (send == null) {
      if (isConstructorName(methodName)) return '';
      return methodName.asIdentifier().source;
    }
    Identifier receiver = send.receiver.asIdentifier();
    Identifier selector = send.selector.asIdentifier();
    Operator operator = selector.asOperator();
    if (operator != null) {
      assert(identical(receiver.source, 'operator'));
      // TODO(ahe): It is a hack to compare to ')', but it beats
      // parsing the node.
      bool isUnary = identical(operator.token.next.next.stringValue, ')');
      return Elements.constructOperatorName(operator.source, isUnary);
    } else {
      if (receiver == null || receiver.source != enclosingClass.name) {
        reporter.reportErrorMessage(
            send.receiver,
            MessageKind.INVALID_CONSTRUCTOR_NAME,
            {'name': enclosingClass.name});
      }
      return selector.source;
    }
  }

  void endMethod(Token getOrSet, Token beginToken, Token endToken) {
    super.endMethod(getOrSet, beginToken, endToken);
    FunctionExpression method = popNode();
    pushNode(null);
    bool isConstructor = isConstructorName(method.name);
    String name = getMethodNameHack(method.name);
    Element memberElement;
    if (isConstructor) {
      if (getOrSet != null) {
        recoverableError(getOrSet, 'illegal modifier');
      }
      memberElement = new PartialConstructorElement(name, beginToken, endToken,
          ElementKind.GENERATIVE_CONSTRUCTOR, method.modifiers, enclosingClass);
    } else {
      memberElement = new PartialFunctionElement(name, beginToken, getOrSet,
          endToken, method.modifiers, enclosingClass,
          hasBody: method.hasBody);
    }
    addMember(memberElement);
  }

  void endFactoryMethod(Token beginToken, Token endToken) {
    super.endFactoryMethod(beginToken, endToken);
    FunctionExpression method = popNode();
    pushNode(null);
    String name = getMethodNameHack(method.name);
    Identifier singleIdentifierName = method.name.asIdentifier();
    if (singleIdentifierName != null && singleIdentifierName.source == name) {
      if (name != enclosingClass.name) {
        reporter.reportErrorMessage(
            singleIdentifierName,
            MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
            {'name': enclosingClass.name});
      }
    }
    Element memberElement = new PartialConstructorElement(
        name,
        beginToken,
        endToken,
        ElementKind.FACTORY_CONSTRUCTOR,
        method.modifiers,
        enclosingClass);
    addMember(memberElement);
  }

  void endFields(int count, Token beginToken, Token endToken) {
    bool hasParseError = memberErrors.head;
    super.endFields(count, beginToken, endToken);
    VariableDefinitions variableDefinitions = popNode();
    Modifiers modifiers = variableDefinitions.modifiers;
    pushNode(null);
    void buildFieldElement(Identifier name, VariableList fields) {
      Element element = new FieldElementX(name, enclosingClass, fields);
      addMember(element);
    }
    buildFieldElements(modifiers, variableDefinitions.definitions,
        enclosingClass, buildFieldElement, beginToken, endToken, hasParseError);
  }

  void endInitializer(Token assignmentOperator) {
    pushNode(null); // Super expects an expression, but
    // ClassElementParser just skips expressions.
    super.endInitializer(assignmentOperator);
  }

  void endInitializers(int count, Token beginToken, Token endToken) {
    pushNode(null);
  }

  void addMetadata(ElementX memberElement) {
    memberElement.metadata = metadata.toList();
  }

  void addMember(ElementX memberElement) {
    addMetadata(memberElement);
    enclosingClass.addMember(memberElement, reporter);
  }

  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
    popNode(); // Discard arguments.
    if (periodBeforeName != null) {
      popNode(); // Discard name.
    }
    popNode(); // Discard node (Send or Identifier).
    pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
  }
}
