Пример #1
0
  private void addStatement(GenerateNodeContext context, Node stmt) {
    CodingConvention convention = compiler.getCodingConvention();

    Node n = context.getNode();
    Node exprRoot = n;
    while (!NodeUtil.isStatementBlock(exprRoot.getParent())) {
      exprRoot = exprRoot.getParent();
    }

    // It's important that any class-building calls (goog.inherits)
    // come right after the class definition, so move the export after that.
    while (true) {
      Node next = exprRoot.getNext();
      if (next != null
          && NodeUtil.isExprCall(next)
          && convention.getClassesDefinedByCall(next.getFirstChild()) != null) {
        exprRoot = next;
      } else {
        break;
      }
    }

    Node block = exprRoot.getParent();
    block.addChildAfter(stmt, exprRoot);
  }
Пример #2
0
  @Override
  public void process(Node externs, Node root) {
    FindExportableNodes findExportableNodes =
        new FindExportableNodes(compiler, allowNonGlobalExports);
    NodeTraversal.traverse(compiler, root, findExportableNodes);
    Map<String, GenerateNodeContext> exports = findExportableNodes.getExports();

    for (Map.Entry<String, GenerateNodeContext> entry : exports.entrySet()) {
      String export = entry.getKey();
      GenerateNodeContext context = entry.getValue();

      if (context.getMode() == Mode.EXPORT) {
        addExportMethod(exports, export, context);
      } else if (context.getMode() == Mode.EXTERN) {
        addExtern(export);
      }
    }
  }
Пример #3
0
  private void addExportMethod(
      Map<String, GenerateNodeContext> exports, String export, GenerateNodeContext context) {
    CodingConvention convention = compiler.getCodingConvention();

    // Emit the proper CALL expression.
    // This is an optimization to avoid exporting everything as a symbol
    // because exporting a property is significantly simpler/faster.
    // Only export the property if the parent is being exported or
    // if the parent is "prototype" and the grandparent is being exported.
    String parent = null;
    String grandparent = null;

    Node node = context.getNode().getFirstChild();
    if (node.isGetProp()) {
      Node parentNode = node.getFirstChild();
      parent = parentNode.getQualifiedName();
      if (parentNode.isGetProp()
          && parentNode.getLastChild().getString().equals(PROTOTYPE_PROPERTY)) {
        grandparent = parentNode.getFirstChild().getQualifiedName();
      }
    }

    boolean useExportSymbol = true;
    if (grandparent != null && exports.containsKey(grandparent)) {
      // grandparent is only set for properties exported off a prototype obj.
      useExportSymbol = false;
    } else if (parent != null && exports.containsKey(parent)) {
      useExportSymbol = false;
    }

    Node call;
    if (useExportSymbol) {
      // exportSymbol(publicPath, object);
      call =
          IR.call(
              NodeUtil.newQualifiedNameNode(
                  convention, exportSymbolFunction, context.getNode(), export),
              IR.string(export),
              NodeUtil.newQualifiedNameNode(convention, export, context.getNode(), export));
    } else {
      // exportProperty(object, publicName, symbol);
      String property = getPropertyName(node);
      call =
          IR.call(
              NodeUtil.newQualifiedNameNode(
                  convention, exportPropertyFunction, context.getNode(), exportPropertyFunction),
              NodeUtil.newQualifiedNameNode(
                  convention, parent, context.getNode(), exportPropertyFunction),
              IR.string(property),
              NodeUtil.newQualifiedNameNode(
                  convention, export, context.getNode(), exportPropertyFunction));
    }

    Node expression = IR.exprResult(call);
    annotate(expression);

    addStatement(context, expression);

    compiler.reportCodeChange();
  }
Пример #4
0
  @Override
  public void process(Node externs, Node root) {
    FindExportableNodes findExportableNodes = new FindExportableNodes(compiler);
    NodeTraversal.traverse(compiler, root, findExportableNodes);
    Map<String, GenerateNodeContext> exports = findExportableNodes.getExports();

    for (Map.Entry<String, GenerateNodeContext> entry : exports.entrySet()) {
      String export = entry.getKey();
      GenerateNodeContext context = entry.getValue();

      // Emit the proper CALL expression.
      // This is an optimization to avoid exporting everything as a symbol
      // because exporting a property is significantly simpler/faster.
      // Only export the property if the parent is being exported or
      // if the parent is "prototype" and the grandparent is being exported.
      String parent = null;
      String grandparent = null;

      Node node = context.getNode().getFirstChild();
      if (node.getType() == Token.GETPROP) {
        parent = node.getFirstChild().getQualifiedName();
        if (node.getFirstChild().getType() == Token.GETPROP
            && getPropertyName(node.getFirstChild()).equals(PROTOTYPE_PROPERTY)) {
          grandparent = node.getFirstChild().getFirstChild().getQualifiedName();
        }
      }

      boolean useExportSymbol = true;
      if (grandparent != null && exports.containsKey(grandparent)) {
        useExportSymbol = false;
      } else if (parent != null && exports.containsKey(parent)) {
        useExportSymbol = false;
      }

      Node call;
      if (useExportSymbol) {
        // exportSymbol(publicPath, object);
        call =
            new Node(
                Token.CALL,
                NodeUtil.newQualifiedNameNode(exportSymbolFunction, context.getNode(), export));
        call.addChildToBack(Node.newString(export));
        call.addChildToBack(NodeUtil.newQualifiedNameNode(export, context.getNode(), export));
      } else {
        // exportProperty(object, publicName, symbol);
        String property = getPropertyName(node);
        call =
            new Node(
                Token.CALL,
                new Node[] {
                  NodeUtil.newQualifiedNameNode(
                      exportPropertyFunction, context.getNode(), exportPropertyFunction),
                  NodeUtil.newQualifiedNameNode(parent, context.getNode(), exportPropertyFunction),
                  Node.newString(property),
                  NodeUtil.newQualifiedNameNode(export, context.getNode(), exportPropertyFunction)
                });
      }

      Node expression = new Node(Token.EXPR_RESULT, call);
      annotate(expression);

      // It's important that any class-building calls (goog.inherits)
      // come right after the class definition, so move the export after that.
      Node insertionPoint = context.getContextNode().getNext();
      CodingConvention convention = compiler.getCodingConvention();
      while (insertionPoint != null
          && NodeUtil.isExprCall(insertionPoint)
          && convention.getClassesDefinedByCall(insertionPoint.getFirstChild()) != null) {
        insertionPoint = insertionPoint.getNext();
      }

      if (insertionPoint == null) {
        context.getScriptNode().addChildToBack(expression);
      } else {
        context.getScriptNode().addChildBefore(expression, insertionPoint);
      }
      compiler.reportCodeChange();
    }
  }