docs: public void run(HtmlMatcherGraph htmlMatcherGraph) {
      if (!htmlMatcherGraph.getRootNode().isPresent()) {
        // Empty graph.
        return;
      }
      visit(htmlMatcherGraph.getRootNode().get());
      for (HtmlTagNode tag : annotationMap.keySet()) {
        if (tag instanceof HtmlOpenTagNode) {
          HtmlOpenTagNode openTag = (HtmlOpenTagNode) tag;
          if (annotationMap.containsEntry(openTag, INVALID_NODE)) {
            if (annotationMap.get(openTag).size() == 1) {
              errorReporter.report(
                  openTag.getSourceLocation(), makeSoyErrorKind(UNEXPECTED_OPEN_TAG_ALWAYS));
            } else {
              errorReporter.report(
                  openTag.getSourceLocation(), makeSoyErrorKind(UNEXPECTED_OPEN_TAG_SOMETIMES));
            }
          }
        }
      }
      // Do not annotate in inCondition because if there are errors, the nodes will be annotated
      // in the parent pass. The reason this happens is when the condition node is not balanced
      // internally but balanced globally.
      if (!errorReporter.getErrors().isEmpty() && inCondition) {
        return;
      }
      for (HtmlTagNode openTag : annotationMap.keySet()) {
        for (Optional<HtmlTagNode> closeTag : annotationMap.get(openTag)) {
          if (closeTag.isPresent()) {
            openTag.addTagPair(closeTag.get());
            closeTag.get().addTagPair(openTag);
          }
        }
      }
    }