// 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 Visitor {
  final TreeElements elements;
  final PlaceholderCollector collector;

  SendVisitor(this.collector, this.elements);

  visitSend(Send node) {
    Element element = elements[node];
    if (elements.isTypeLiteral(node)) {
      DartType type = elements.getTypeLiteralType(node);
      if (!type.isDynamic) {
        if (type is TypeVariableType) {
          collector.makeTypeVariablePlaceholder(node.selector, type);
        } else {
          collector.makeTypePlaceholder(node.selector, type);
        }
      }
    } else if (node.isSuperCall) {
      if (element != null && element.isConstructor) {
        collector.tryMakeConstructorPlaceholder(node, element);
      } else {
        collector.tryMakeMemberPlaceholder(node.selector);
      }
    } else if (node.isOperator) {
      return;
    } else if (node.isPropertyAccess) {
      if (!Elements.isUnresolved(element) && element.impliesType) {
        collector.makeElementPlaceholder(node, element);
      } else {
        visitGetterSend(node);
      }
    } else if (element != null && Initializers.isConstructorRedirect(node)) {
      visitStaticSend(node);
    } else if (Elements.isClosureSend(node, element)) {
      if (element != null) {
        collector.tryMakeLocalPlaceholder(element, node.selector);
      }
    } else {
      if (Elements.isUnresolved(element)) {
        if (element == null) {
          // Example: f() with 'f' unbound.
          // This can only happen inside an instance method.
          visitDynamicSend(node);
        } else {
          visitStaticSend(node);
        }
      } else if (element.isInstanceMember) {
        // Example: f() with 'f' bound to instance method.
        visitDynamicSend(node);
      } else if (!element.isInstanceMember) {
        // Example: A.f() or f() with 'f' bound to a static function.
        // Also includes new A() or new A.named() which is treated like a
        // static call to a factory.
        visitStaticSend(node);
      }
    }
  }

  visitDynamicSend(Send node) {
    final element = elements[node];
    if (element == null || !element.isErroneous) {
      collector.tryMakeMemberPlaceholder(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);
        }
      }
    }
  }

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

    if (Elements.isUnresolved(element)
        || 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(Spannable node, String reason) {
    collector.internalError(reason, node: node);
  }

  visitNode(Node node) {
    internalError(node, "Unhandled node");
  }
}

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;
    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.isAccessor) {
      element = (element as AccessorElement).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) &&
        Name.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;
      List<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);
  }
}
