// 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;
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) {
    super.endMetadata(beginToken, periodBeforeName, endToken);
    pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
  }
}
