Package com.google.template.soy.sharedpasses

Source Code of com.google.template.soy.sharedpasses.CombineConsecutiveRawTextNodesVisitor

/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.template.soy.sharedpasses;

import com.google.common.collect.Lists;
import com.google.template.soy.base.IdGenerator;
import com.google.template.soy.soytree.AbstractSoyNodeVisitor;
import com.google.template.soy.soytree.RawTextNode;
import com.google.template.soy.soytree.SoyFileSetNode;
import com.google.template.soy.soytree.SoyNode;
import com.google.template.soy.soytree.SoyNode.BlockNode;
import com.google.template.soy.soytree.SoyNode.ParentSoyNode;
import com.google.template.soy.soytree.SoyNode.StandaloneNode;

import java.util.List;


/**
* Visitor for combining any consecutive sequences of {@code RawTextNode}s into one equivalent
* {@code RawTextNode}.
*
* <p> Important: Do not use outside of Soy code (treat as superpackage-private).
*
* @author Kai Huang
*/
public class CombineConsecutiveRawTextNodesVisitor extends AbstractSoyNodeVisitor<Void> {


  /** The node id generator for the parse tree. Retrieved from the root SoyFileSetNode. */
  private IdGenerator nodeIdGen;


  @Override public Void exec(SoyNode node) {

    // Retrieve the node id generator from the root of the parse tree.
    nodeIdGen = node.getNearestAncestor(SoyFileSetNode.class).getNodeIdGenerator();

    // Execute the pass.
    return super.exec(node);
  }


  @Override protected void visitSoyNode(SoyNode node) {

    if (node instanceof ParentSoyNode<?>) {
      visitChildren((ParentSoyNode<?>) node);
    }

    if (! (node instanceof BlockNode)) {
      return;
    }
    BlockNode nodeAsBlock = (BlockNode) node;

    // Check whether there are any consecutive RawTextNode children.
    boolean hasConsecRawTextNodes = false;
    for (int i = 0; i <= nodeAsBlock.numChildren() - 2; i++) {
      if (nodeAsBlock.getChild(i) instanceof RawTextNode &&
          nodeAsBlock.getChild(i+1) instanceof RawTextNode) {
        hasConsecRawTextNodes = true;
        break;
      }
    }
    // If there aren't any consecutive RawTextNode children, we're done.
    if (!hasConsecRawTextNodes) {
      return;
    }

    // Rebuild the list of children, combining consecutive RawTextNodes into one.
    List<StandaloneNode> copyOfOrigChildren = Lists.newArrayList(nodeAsBlock.getChildren());
    nodeAsBlock.clearChildren();

    List<RawTextNode> consecutiveRawTextNodes = Lists.newArrayList();
    for (StandaloneNode origChild : copyOfOrigChildren) {

      if (origChild instanceof RawTextNode) {
        consecutiveRawTextNodes.add((RawTextNode) origChild);

      } else {
        // First add the preceding consecutive RawTextNodes, if any.
        addConsecutiveRawTextNodesAsOneNodeHelper(nodeAsBlock, consecutiveRawTextNodes);
        consecutiveRawTextNodes.clear();
        // Then add the current new child.
        nodeAsBlock.addChild(origChild);
      }
    }

    // Add the final group of consecutive RawTextNodes, if any.
    addConsecutiveRawTextNodesAsOneNodeHelper(nodeAsBlock, consecutiveRawTextNodes);
    consecutiveRawTextNodes.clear();
  }


  /**
   * Helper to add consecutive RawTextNodes as one child node (the raw text will be joined).
   * If the consecutive RawTextNodes list actually only has one item, then adds that node instead
   * of creating a new RawTextNode.
   *
   * Note: This function works closely with the above code. In particular, it assumes we're
   * rebuilding the whole list (thus adding to the end of the parent) instead of fixing the old
   * list in-place.
   *
   * @param parent The parent to add the new child to.
   * @param consecutiveRawTextNodes The list of consecutive RawTextNodes.
   */
  private void addConsecutiveRawTextNodesAsOneNodeHelper(
      BlockNode parent, List<RawTextNode> consecutiveRawTextNodes) {

    if (consecutiveRawTextNodes.size() == 0) {
      return;
    } else if (consecutiveRawTextNodes.size() == 1) {
      // Simply add the one RawTextNode.
      parent.addChild(consecutiveRawTextNodes.get(0));
    } else {
      // Create a new combined RawTextNode.
      StringBuilder rawText = new StringBuilder();
      for (RawTextNode rtn : consecutiveRawTextNodes) {
        rawText.append(rtn.getRawText());
      }
      parent.addChild(new RawTextNode(nodeIdGen.genId(), rawText.toString()));
    }
  }

}
TOP

Related Classes of com.google.template.soy.sharedpasses.CombineConsecutiveRawTextNodesVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.