code: @Nullable
    private static String getFullTagText(HtmlTagNode openTagNode) {
      class Visitor implements NodeVisitor<Node, VisitDirective> {
        boolean isConstantContent = true;
  
        @Override
        public VisitDirective exec(Node node) {
          if (node instanceof RawTextNode
              || node instanceof HtmlAttributeNode
              || node instanceof HtmlAttributeValueNode
              || node instanceof HtmlOpenTagNode
              || node instanceof HtmlCloseTagNode) {
            return VisitDirective.CONTINUE;
          }
          isConstantContent = false;
          return VisitDirective.ABORT;
        }
      }
      Visitor visitor = new Visitor();
      SoyTreeUtils.visitAllNodes(openTagNode, visitor);
      if (visitor.isConstantContent) {
        // toSourceString is lame, but how this worked before
        return openTagNode.toSourceString();
      }
      return null;
    }
docs: This method calculates a string that can be used to tell if two tags that were turned into
  placeholders are equivalent and thus could be turned into identical placeholders.
  
  <p>In theory we should use something like {@link ExprEquivalence} to see if two nodes would
  render the same thing. However, for backwards compatibility we need to use a different
  heuristic. The old code would simply detect if the node had a single child and use the {@link
  SoyNode#toSourceString()} of it for the tag text. Due to how the children were constructed,
  this would only happen if the tag was a single {@link RawTextNode}, e.g. {@code <foo
  class=bar>}. Now that we are actually parsing the html tags the rules are more complex. We
  should instead only use the {@link SoyNode#toSourceString()} if the only (transitive) children
  are {@link RawTextNode}, {@link HtmlAttributeNode} or {@link HtmlAttributeValueNode}.