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

part of dart_backend;

class LocalPlaceholder {
  final String identifier;
  final Set<Node> nodes;
  LocalPlaceholder(this.identifier) : nodes = new Set<Node>();
  int get hashCode => identifier.hashCode;
  String toString() =>
      'local_placeholder[id($identifier), nodes($nodes)]';
}

class FunctionScope {
  final Set<String> parameterIdentifiers;
  final Set<LocalPlaceholder> localPlaceholders;
  FunctionScope()
      : parameterIdentifiers = new Set<String>(),
      localPlaceholders = new Set<LocalPlaceholder>();
  void registerParameter(Identifier node) {
    parameterIdentifiers.add(node.source);
  }
}

class ConstructorPlaceholder {
  final Identifier node;
  final ConstructorElement element;

  ConstructorPlaceholder(this.node, this.element);
}

class DeclarationTypePlaceholder {
  final TypeAnnotation typeNode;
  final bool requiresVar;
  DeclarationTypePlaceholder(this.typeNode, this.requiresVar);
}

class SendVisitor extends ResolvedVisitor {
  final PlaceholderCollector collector;

  SendVisitor(this.collector, TreeElements elements)
      : super(elements);

  visitOperatorSend(Send node) {
  }

  visitForeignSend(Send node) {}

  visitSuperSend(Send node) {
    Element element = elements[node];
    if (element != null && element.isConstructor) {
      collector.tryMakeConstructorPlaceholder(node, element);
    } else {
      collector.tryMakeMemberPlaceholder(node.selector);
    }
  }

  visitDynamicSend(Send node) {
    final element = elements[node];
    if (element == null || !element.isErroneous) {
      collector.tryMakeMemberPlaceholder(node.selector);
    }
  }

  visitClosureSend(Send node) {
    final element = elements[node];
    if (element != null) {
      collector.tryMakeLocalPlaceholder(element, node.selector);
    }
  }

  visitGetterSend(Send node) {
    final element = elements[node];
    // element == null means dynamic property access.
    if (element == null) {
      collector.tryMakeMemberPlaceholder(node.selector);
    } else if (element.isErroneous) {
      collector.makeUnresolvedPlaceholder(node);
      return;
    } else if (element.isPrefix) {
      // Node is prefix part in case of source 'lib.somesetter = 5;'
      collector.makeErasePrefixPlaceholder(node);
    } else if (Elements.isStaticOrTopLevel(element)) {
      // Unqualified or prefixed top level or static.
      collector.makeElementPlaceholder(node.selector, element);
    } else if (!element.isTopLevel) {
      if (element.isInstanceMember) {
        collector.tryMakeMemberPlaceholder(node.selector);
      } else {
        // May get FunctionExpression here in selector
        // in case of A(int this.f());
        if (node.selector is Identifier) {
          collector.tryMakeLocalPlaceholder(element, node.selector);
        } else {
          assert(node.selector is FunctionExpression);
        }
      }
    }
  }

  visitAssert(node) {
    visitStaticSend(node);
  }

  visitStaticSend(Send node) {
    Element element = elements[node];
    collector.mirrorRenamer.registerStaticSend(
        collector.currentElement, element, node);

    if (Elements.isUnresolved(element)
        || elements.isAssert(node)
        || element.isDeferredLoaderGetter) {
      return;
    }
    if (element.isConstructor || element.isFactoryConstructor) {
      // Rename named constructor in redirection position:
      // class C { C.named(); C.redirecting() : this.named(); }
      if (node.receiver is Identifier
          && node.receiver.asIdentifier().isThis()) {
        assert(node.selector is Identifier);
        collector.tryMakeConstructorPlaceholder(node, element);
      }
      return;
    }
    collector.makeElementPlaceholder(node.selector, element);
    // Another ugly case: <lib prefix>.<top level> is represented as
    // receiver: lib prefix, selector: top level.
    if (element.isTopLevel && node.receiver != null) {
      assert(elements[node.receiver].isPrefix);
      // Hack: putting null into map overrides receiver of original node.
      collector.makeErasePrefixPlaceholder(node.receiver);
    }
  }

  internalError(String reason, {Node node}) {
    collector.internalError(reason, node: node);
  }

  visitTypePrefixSend(Send node) {
    collector.makeElementPlaceholder(node, elements[node]);
  }

  visitTypeLiteralSend(Send node) {
    DartType type = elements.getTypeLiteralType(node);
    if (!type.isDynamic) {
      if (type is TypeVariableType) {
        collector.makeTypeVariablePlaceholder(node.selector, type);
      } else {
        collector.makeTypePlaceholder(node.selector, type);
      }
    }
  }
}

class PlaceholderCollector extends Visitor {
  final DiagnosticListener listener;
  final MirrorRenamer mirrorRenamer;
  final FunctionElement mainFunction;
  final Set<String> fixedMemberNames; // member names which cannot be renamed.
  final Map<Element, ElementAst> elementAsts;
  final Set<Node> prefixNodesToErase = new Set<Node>();
  final Set<Node> unresolvedNodes = new Set<Node>();
  final Map<Element, Set<Node>> elementNodes = new Map<Element, Set<Node>>();
  final Map<FunctionElement, FunctionScope> functionScopes
      = new Map<FunctionElement, FunctionScope>();
  final Map<LibraryElement, Set<Identifier>> privateNodes =
      new Map<LibraryElement, Set<Identifier>>();
  final List<DeclarationTypePlaceholder> declarationTypePlaceholders
      = new List<DeclarationTypePlaceholder>();
  final Map<String, Set<Identifier>> memberPlaceholders
      = new Map<String, Set<Identifier>>();
  final List<ConstructorPlaceholder> constructorPlaceholders
      = new List<ConstructorPlaceholder>();
  Map<String, LocalPlaceholder> currentLocalPlaceholders;
  Element currentElement;
  FunctionElement topmostEnclosingFunction;
  TreeElements treeElements;

  get currentFunctionScope => functionScopes.putIfAbsent(
      topmostEnclosingFunction, () => new FunctionScope());

  PlaceholderCollector(this.listener, this.mirrorRenamer,
                       this.fixedMemberNames, this.elementAsts,
                       this.mainFunction);

  void collectFunctionDeclarationPlaceholders(
      FunctionElement element, FunctionExpression node) {
    if (element.isConstructor) {
      ConstructorElement constructor = element;
      tryMakeConstructorPlaceholder(node.name, element);
      RedirectingFactoryBody bodyAsRedirectingFactoryBody =
          node.body.asRedirectingFactoryBody();
      if (bodyAsRedirectingFactoryBody != null) {
        // Factory redirection.
        FunctionElement redirectTarget = constructor.immediateRedirectionTarget;
        assert(redirectTarget != null && redirectTarget != element);
        tryMakeConstructorPlaceholder(
            bodyAsRedirectingFactoryBody.constructorReference,
            redirectTarget);
      }
    } else if (Elements.isStaticOrTopLevel(element)) {
      // Note: this code should only rename private identifiers for class'
      // fields/getters/setters/methods.  Top-level identifiers are renamed
      // just to escape conflicts and that should be enough as we shouldn't
      // be able to resolve private identifiers for other libraries.
      makeElementPlaceholder(node.name, element);
    } else if (element.isClassMember) {
      if (node.name is Identifier) {
        tryMakeMemberPlaceholder(node.name);
      } else {
        assert(node.name.asSend().isOperator);
      }
    }
  }

  void collectFieldDeclarationPlaceholders(Element element, Node node) {
    Identifier name = node is Identifier ? node : node.asSend().selector;
    if (Elements.isStaticOrTopLevel(element)) {
      makeElementPlaceholder(name, element);
    } else if (Elements.isInstanceField(element)) {
      tryMakeMemberPlaceholder(name);
    }
  }

  void collect(Element element) {
    this.currentElement = element;
    this.topmostEnclosingFunction = null;
    final ElementAst elementAst = elementAsts[element];
    this.treeElements = elementAst.treeElements;
    Node elementNode = elementAst.ast;
    if (element is FunctionElement) {
      collectFunctionDeclarationPlaceholders(element, elementNode);
    } else if (element is VariableElement) {
      VariableDefinitions definitions = elementNode;
      Node definition = definitions.definitions.nodes.head;
      collectFieldDeclarationPlaceholders(element, definition);
      makeVarDeclarationTypePlaceholder(definitions);
    } else {
      assert(element is ClassElement || element is TypedefElement);
    }
    currentLocalPlaceholders = new Map<String, LocalPlaceholder>();
    if (!(element is ConstructorElement && element.isRedirectingFactory)) {
      // Do not visit the body of redirecting factories.
      listener.withCurrentElement(element, () {
        elementNode.accept(this);
      });
    }
  }

  // TODO(karlklose): should we create placeholders for these?
  bool isTypedefParameter(Element element) {
    return element != null &&
        element.enclosingElement != null &&
        element.enclosingElement.isTypedef;
  }

  void tryMakeLocalPlaceholder(Element element, Identifier node) {
    bool isNamedOptionalParameter() {
      FunctionTypedElement function = element.enclosingElement;
      FunctionSignature signature = function.functionSignature;
      if (!signature.optionalParametersAreNamed) return false;
      for (Element parameter in signature.optionalParameters) {
        if (identical(parameter, element)) return true;
      }
      return false;
    }
    if (element.isParameter && !isTypedefParameter(element) &&
        isNamedOptionalParameter()) {
      currentFunctionScope.registerParameter(node);
    } else if (Elements.isLocal(element) && !isTypedefParameter(element)) {
      makeLocalPlaceholder(node);
    }
  }

  void tryMakeMemberPlaceholder(Identifier node) {
    assert(node != null);
    if (node is Operator) return;
    String identifier = node.source;
    if (fixedMemberNames.contains(identifier)) return;
    memberPlaceholders.putIfAbsent(
        identifier, () => new Set<Identifier>()).add(node);
  }

  void makeTypePlaceholder(Node node, DartType type) {
    Send send = node.asSend();
    if (send != null) {
      // Prefix.
      assert(send.receiver is Identifier);
      assert(send.selector is Identifier);
      makeErasePrefixPlaceholder(send.receiver);
      node = send.selector;
    }
    makeElementPlaceholder(node, type.element);
  }

  void makeTypeVariablePlaceholder(Node node, TypeVariableType type) {
    Send send = node.asSend();
    if (send != null) {
      // Prefix.
      assert(send.receiver is Identifier);
      assert(send.selector is Identifier);
      makeErasePrefixPlaceholder(send.receiver);
      node = send.selector;
    }
    tryMakeMemberPlaceholder(node);
  }

  void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) {
    if (type == null) return;
    declarationTypePlaceholders.add(
        new DeclarationTypePlaceholder(type, false));
  }

  void makeVarDeclarationTypePlaceholder(VariableDefinitions node) {
    // TODO(smok): Maybe instead of calling this method and
    // makeDeclaratioTypePlaceholder have type declaration placeholder
    // collector logic in visitVariableDefinitions when resolver becomes better
    // and/or catch syntax changes.
    if (node.type == null) return;
    Element definitionElement = treeElements[node.definitions.nodes.head];
    bool requiresVar = !node.modifiers.isFinalOrConst;
    declarationTypePlaceholders.add(
        new DeclarationTypePlaceholder(node.type, requiresVar));
  }

  /// Marks [node] to be erased in the output.
  /// This is done for library prefixes because they are not used in the output
  /// because all imports are flattened and conflicts are renamed away.
  void makeErasePrefixPlaceholder(Node node) {
    assert(node is Identifier || node is Send);
    prefixNodesToErase.add(node);
  }

  void makeElementPlaceholder(Node node, Element element) {
    assert(node != null);
    assert(element != null);
    LibraryElement library = element.library;
    if (identical(element, mainFunction)) return;
    if (library.isDartCore) return;

    if (library.isPlatformLibrary && !element.isTopLevel) {
      return;
    }

    ClassElement cls = element.enclosingClass;
    if (cls != null && cls.isEnumClass) {
      // Enums and enum values cannot be changed, since the semantics of
      // `toString` is defined by the names of the declarations.
      return;
    }

    if (element.isGetter || element.isSetter) {
      element = (element as FunctionElement).abstractField;
    }
    elementNodes.putIfAbsent(element, () => new Set<Node>()).add(node);
  }

  /// Marks [node] to be renamed per-library if it names an instance member
  /// and has a private name.
  void tryMakePrivateIdentifier(Node node, Element element) {
    if (node is Identifier &&
        !Elements.isStaticOrTopLevel(element) &&
        !Elements.isLocal(element) &&
        isPrivateName(node.source)) {
      privateNodes.putIfAbsent(
          currentElement.library, () => new Set<Identifier>()).add(node);
    }
  }

  void makeUnresolvedPlaceholder(Node node) {
    unresolvedNodes.add(node);
  }

  void makeLocalPlaceholder(Identifier identifier) {
    LocalPlaceholder getLocalPlaceholder() {
      String name = identifier.source;
      return currentLocalPlaceholders.putIfAbsent(name, () {
        LocalPlaceholder localPlaceholder = new LocalPlaceholder(name);
        currentFunctionScope.localPlaceholders.add(localPlaceholder);
        return localPlaceholder;
      });
    }
    getLocalPlaceholder().nodes.add(identifier);
  }

  /// Finds the first constructor on the chain of definingConstructor from
  /// [element] that is not in a synthetic class.
  Element findDefiningConstructor(ConstructorElement element) {
    while (element.definingConstructor != null) {
      element = element.definingConstructor;
    }
    return element;
  }

  void tryMakeConstructorPlaceholder(Node node, ConstructorElement element) {
    if (Elements.isUnresolved(element)) {
      makeUnresolvedPlaceholder(node);
      return;
    }
    // A library prefix.
    Node prefix;
    // The name of the class with the constructor.
    Node className;
    // Will be null for unnamed constructors.
    Identifier constructorName;
    // First deconstruct the constructor, there are 4 possibilities:
    //  ClassName()
    //  prefix.ClassName()
    //  ClassName.constructorName()
    //  prefix.ClassName.constructorName()
    if (node is Send) {
      if (node.receiver is Send) {
        Send receiver = node.receiver;
        // prefix.ClassName.constructorName()
        assert(treeElements[receiver.receiver] != null &&
               treeElements[receiver.receiver].isPrefix);
        prefix = receiver.receiver;
        className = receiver.selector;
        constructorName = node.selector;
      } else {
        Element receiverElement = treeElements[node.receiver];
        if (receiverElement != null && receiverElement.isPrefix) {
          // prefix.ClassName()
          prefix = node.receiver;
          className = node.selector;
        } else {
          // ClassName.constructorName()
          className = node.receiver;
          constructorName = node.selector;
        }
      }
    } else {
      // ClassName()
      className = node;
    }

    if (prefix != null) {
      makeErasePrefixPlaceholder(prefix);
    }

    if (className is TypeAnnotation) {
      visitTypeAnnotation(className);
    } else if (Elements.isUnresolved(element)) {
      // We handle unresolved nodes elsewhere.
    } else if (className.isThis() || className.isSuper()) {
      // Do not rename super and this.
    } else if (className is Identifier) {
      makeElementPlaceholder(className, element.contextClass);
    } else {
      throw "Bad type of constructor name $className";
    }

    if (constructorName != null) {
      Element definingConstructor = findDefiningConstructor(element);
      constructorPlaceholders.add(new ConstructorPlaceholder(constructorName,
          definingConstructor));
      tryMakePrivateIdentifier(constructorName, element);
    }
  }

  void internalError(String reason, {Node node}) {
    listener.internalError(node, reason);
  }

  visit(Node node) => (node == null) ? null : node.accept(this);

  visitNode(Node node) { node.visitChildren(this); }  // We must go deeper.

  visitNewExpression(NewExpression node) {
    Send send = node.send;
    DartType type = treeElements.getType(node);
    assert(type != null);
    Element constructor = treeElements[send];
    assert(constructor != null);
    assert(send.receiver == null);
    if (!Elements.isErroneous(constructor)) {
      tryMakeConstructorPlaceholder(node.send.selector, constructor);
      // TODO(smok): Should this be in visitNamedArgument?
      // Field names can be exposed as names of optional arguments, e.g.
      // class C {
      //   final field;
      //   C([this.field]);
      // }
      // Do not forget to rename them as well.
      FunctionElement constructorFunction = constructor;
      Link<Element> optionalParameters =
          constructorFunction.functionSignature.optionalParameters;
      for (final argument in send.argumentsNode) {
        NamedArgument named = argument.asNamedArgument();
        if (named == null) continue;
        Identifier name = named.name;
        String nameAsString = name.source;
        for (final parameter in optionalParameters) {
          if (parameter.isInitializingFormal) {
            if (parameter.name == nameAsString) {
              tryMakeMemberPlaceholder(name);
              break;
            }
          }
        }
      }
    } else {
      makeUnresolvedPlaceholder(node.send.selector);
    }
    visit(node.send.argumentsNode);
  }

  visitSend(Send send) {
    Element element = treeElements[send];
    tryMakePrivateIdentifier(send.selector, element);
    new SendVisitor(this, treeElements).visitSend(send);
    send.visitChildren(this);
  }

  visitSendSet(SendSet send) {
    Element element = treeElements[send];
    if (Elements.isErroneous(element)) {
      // Complicated case: constructs like receiver.selector++ can resolve
      // to ErroneousElement.  Fortunately, receiver.selector still
      // can be resoved via treeElements[send.selector], that's all
      // that is needed to rename the construct properly.
      element = treeElements[send.selector];
    }
    tryMakePrivateIdentifier(send.selector, element);
    if (element == null) {
      if (send.receiver != null) tryMakeMemberPlaceholder(send.selector);
    } else if (!element.isErroneous) {
      if (Elements.isStaticOrTopLevel(element)) {
        // TODO(smok): Worth investigating why sometimes we get getter/setter
        // here and sometimes abstract field.
        assert(element.isClass || element is VariableElement ||
               element.isAccessor || element.isAbstractField ||
               element.isFunction || element.isTypedef ||
               element is TypeVariableElement);
        makeElementPlaceholder(send.selector, element);
      } else {
        Identifier identifier = send.selector.asIdentifier();
        if (identifier == null) {
          // Handle optional function expression parameters with default values.
          identifier = send.selector.asFunctionExpression().name;
        }
        if (Elements.isInstanceField(element)) {
          tryMakeMemberPlaceholder(identifier);
        } else {
          tryMakeLocalPlaceholder(element, identifier);
        }
      }
    }
    send.visitChildren(this);
  }

  visitTypeAnnotation(TypeAnnotation node) {
    final type = treeElements.getType(node);
    assert(invariant(node, type != null,
        message: "Missing type for type annotation: $treeElements"));
    if (!type.isVoid) {
      if (!type.treatAsDynamic) {
        if (type is TypeVariableType) {
          makeTypeVariablePlaceholder(node.typeName, type);
        } else {
          makeTypePlaceholder(node.typeName, type);
        }
      } else if (!type.isDynamic) {
        makeUnresolvedPlaceholder(node.typeName);
      }
    }
    // Visit only type arguments, otherwise in case of lib.Class type
    // annotation typeName is Send and we go to visitGetterSend, as a result
    // "Class" is added to member placeholders.
    visit(node.typeArguments);
  }

  visitVariableDefinitions(VariableDefinitions node) {
    // Collect only local placeholders.
    for (Node definition in node.definitions.nodes) {
      Element definitionElement = treeElements[definition];
      // definitionElement may be null if we're inside variable definitions
      // of a function that is a parameter of another function.
      // TODO(smok): Fix this when resolver correctly deals with
      // such cases.
      if (definitionElement == null) continue;

      Send send = definition.asSend();
      Identifier identifier = definition is Identifier
          ? definition
          : definition is Send
              ? (send.selector is Identifier
                  ? send.selector
                  : null)
              : null;

      tryMakePrivateIdentifier(identifier, definitionElement);

      if (send != null) {
        // May get FunctionExpression here in definition.selector
        // in case of A(int this.f());
        if (send.selector is Identifier) {
          if (definitionElement.isInitializingFormal) {
            tryMakeMemberPlaceholder(send.selector);
          } else {
            tryMakeLocalPlaceholder(definitionElement, send.selector);
          }
        } else {
          assert(send.selector is FunctionExpression);
          if (definitionElement.isInitializingFormal) {
            tryMakeMemberPlaceholder(
                send.selector.asFunctionExpression().name);
          }
        }
      } else if (definition is Identifier) {
        tryMakeLocalPlaceholder(definitionElement, definition);
      } else if (definition is FunctionExpression) {
        // Skip, it will be processed in visitFunctionExpression.
      } else {
        internalError('Unexpected definition structure $definition');
      }
    }
    node.visitChildren(this);
  }

  visitFunctionExpression(FunctionExpression node) {
    bool isKeyword(Identifier id) =>
        id != null && Keyword.keywords[id.source] != null;

    Element element = treeElements[node];
    // May get null;
    if (element != null) {
      tryMakePrivateIdentifier(node.name, element);

      // Rename only local functions.
      if (topmostEnclosingFunction == null &&
          element is! LocalParameterElement &&
          element is! InitializingFormalElement) {
        topmostEnclosingFunction = element;
      }
      if (!identical(element, currentElement)) {
        if (node.name != null) {
          assert(node.name is Identifier);
          tryMakeLocalPlaceholder(element, node.name);
        }
      }
    }

    node.visitChildren(this);

    // Make sure we don't omit return type of methods which names are
    // identifiers, because the following works fine:
    // int interface() => 1;
    // But omitting 'int' makes VM unhappy.
    // TODO(smok): Remove it when http://dartbug.com/5278 is fixed.
    if (node.name == null || !isKeyword(node.name.asIdentifier())) {
      makeOmitDeclarationTypePlaceholder(node.returnType);
    }
    collectFunctionParameters(node.parameters);
  }

  void collectFunctionParameters(NodeList parameters) {
    if (parameters == null) return;
    for (Node parameter in parameters.nodes) {
      if (parameter is NodeList) {
        // Optional parameter list.
        collectFunctionParameters(parameter);
      } else {
        assert(parameter is VariableDefinitions);
        makeOmitDeclarationTypePlaceholder(
            parameter.asVariableDefinitions().type);
      }
    }
  }

  visitClassNode(ClassNode node) {
    ClassElement classElement = currentElement;
    makeElementPlaceholder(node.name, classElement);
    node.visitChildren(this);
  }

  visitNamedMixinApplication(NamedMixinApplication node) {
    ClassElement classElement = currentElement;
    makeElementPlaceholder(node.name, classElement);
    node.visitChildren(this);
  }

  visitTypeVariable(TypeVariable node) {
    DartType type = treeElements.getType(node);
    assert(invariant(node, type != null,
        message: "Missing type for type variable: $treeElements"));
    makeTypeVariablePlaceholder(node.name, type);
    node.visitChildren(this);
  }

  visitTypedef(Typedef node) {
    assert(currentElement is TypedefElement);
    makeElementPlaceholder(node.name, currentElement);
    node.visitChildren(this);
    makeOmitDeclarationTypePlaceholder(node.returnType);
    collectFunctionParameters(node.formals);
  }

  visitBlock(Block node) {
    for (Node statement in node.statements.nodes) {
      if (statement is VariableDefinitions) {
        makeVarDeclarationTypePlaceholder(statement);
      }
    }
    node.visitChildren(this);
  }
}
