/*
 * Copyright 2017 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.soytree;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.basetree.CopyState;
import com.google.template.soy.soytree.SoyNode.StandaloneNode;
import javax.annotation.Nullable;

/**
 * Base class for html tags. Provides easy access to the {@link TagName}.
 *
 * <p>The first child is guaranteed to be the tag name, any after that are guaranteed to be in
 * attribute context. There is always at least one child.
 */
public abstract class HtmlTagNode extends AbstractParentSoyNode<StandaloneNode>
    implements StandaloneNode {

  private final TagName tagName;

  protected HtmlTagNode(int id, TagName tagName, SourceLocation sourceLocation) {
    super(id, sourceLocation);
    this.tagName = checkNotNull(tagName);
  }

  protected HtmlTagNode(HtmlTagNode orig, CopyState copyState) {
    super(orig, copyState);
    this.tagName = orig.tagName;
  }

  @SuppressWarnings("unchecked")
  @Override
  public final ParentSoyNode<StandaloneNode> getParent() {
    return (ParentSoyNode<StandaloneNode>) super.getParent();
  }

  public final TagName getTagName() {
    return tagName;
  }

  /** Returns an attribute with the given static name if it is a direct child. */
  @Nullable
  public HtmlAttributeNode getDirectAttributeNamed(String attrName) {
    // the child at index 0 is the tag name
    for (int i = 1; i < numChildren(); i++) {
      StandaloneNode child = getChild(i);
      if (child instanceof HtmlAttributeNode) {
        HtmlAttributeNode attr = (HtmlAttributeNode) child;
        if (attr.definitelyMatchesAttributeName(attrName)) {
          return attr;
        }
      }
    }
    return null;
  }
}

@@ -847,30 +847,143 @@
 SoyNode.
-StandaloneNode
+ParentSoyNode;%0Aimport com.google.template.soy.soytree.SoyNode.StandaloneNode;%0Aimport java.util.ArrayList;%0Aimport java.util.List
 ;%0Aimport
@@ -1396,16 +1396,445 @@
 gName;%0A%0A
+  /**%0A   * Represents a list of tags that this HtmlTagNode might be paired with. For example, if we have%0A   * an element %60%3Cdiv%3E%3C/div%3E%60, the HTMLOpenTagNode would have the HTMLCloseTagNode in its%0A   * taggedPairs (and vice versa). This is a list because an open tag node might have multiple close%0A   * tag nodes (and vice versa) depending on control flow.%0A   */%0A  private final List%3CHtmlTagNode%3E taggedPairs = new ArrayList%3C%3E();%0A%0A
   protec
@@ -2321,24 +2321,24 @@
 TagName() %7B%0A
-
     return t
@@ -2350,16 +2350,178 @@
 e;%0A  %7D%0A%0A
+  public List%3CHtmlTagNode%3E getTaggedPairs() %7B%0A    return this.taggedPairs;%0A  %7D%0A%0A  public void addTagPair(HtmlTagNode node) %7B%0A    this.taggedPairs.add(node);%0A  %7D%0A%0A
   /** Re

Add an API to annotate open/close pairs.