//===- HTMLDiagnostics.cpp - HTML Diagnostics for Paths -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the HTMLDiagnostics object.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// Boilerplate.
//===----------------------------------------------------------------------===//

namespace {

class HTMLDiagnostics : public PathDiagnosticConsumer {
  std::string Directory;
  bool createdDir = false;
  bool noDir = false;
  const Preprocessor &PP;
  AnalyzerOptions &AnalyzerOpts;
  const bool SupportsCrossFileDiagnostics;

public:
  HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
                  const std::string& prefix,
                  const Preprocessor &pp,
                  bool supportsMultipleFiles)
      : Directory(prefix), PP(pp), AnalyzerOpts(AnalyzerOpts),
        SupportsCrossFileDiagnostics(supportsMultipleFiles) {}

  ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }

  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
                            FilesMade *filesMade) override;

  StringRef getName() const override {
    return "HTMLDiagnostics";
  }

  bool supportsCrossFileDiagnostics() const override {
    return SupportsCrossFileDiagnostics;
  }

  unsigned ProcessMacroPiece(raw_ostream &os,
                             const PathDiagnosticMacroPiece& P,
                             unsigned num);

  void HandlePiece(Rewriter &R, FileID BugFileID, const PathDiagnosticPiece &P,
                   const std::vector<SourceRange> &PopUpRanges, unsigned num,
                   unsigned max);

  void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
                      const char *HighlightStart = "<span class=\"mrange\">",
                      const char *HighlightEnd = "</span>");

  void ReportDiag(const PathDiagnostic& D,
                  FilesMade *filesMade);

  // Generate the full HTML report
  std::string GenerateHTML(const PathDiagnostic& D, Rewriter &R,
                           const SourceManager& SMgr, const PathPieces& path,
                           const char *declName);

  // Add HTML header/footers to file specified by FID
  void FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
                    const SourceManager& SMgr, const PathPieces& path,
                    FileID FID, const FileEntry *Entry, const char *declName);

  // Rewrite the file specified by FID with HTML formatting.
  void RewriteFile(Rewriter &R, const PathPieces& path, FileID FID);


private:
  /// \return Javascript for displaying shortcuts help;
  StringRef showHelpJavascript();

  /// \return Javascript for navigating the HTML report using j/k keys.
  StringRef generateKeyboardNavigationJavascript();

  /// \return JavaScript for an option to only show relevant lines.
  std::string showRelevantLinesJavascript(
    const PathDiagnostic &D, const PathPieces &path);

  /// Write executed lines from \p D in JSON format into \p os.
  void dumpCoverageData(const PathDiagnostic &D,
                        const PathPieces &path,
                        llvm::raw_string_ostream &os);
};

} // namespace

void ento::createHTMLDiagnosticConsumer(
    AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
    const std::string &prefix, const Preprocessor &PP,
    const cross_tu::CrossTranslationUnitContext &) {
  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, true));
}

void ento::createHTMLSingleFileDiagnosticConsumer(
    AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
    const std::string &prefix, const Preprocessor &PP,
    const cross_tu::CrossTranslationUnitContext &) {
  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, false));
}

//===----------------------------------------------------------------------===//
// Report processing.
//===----------------------------------------------------------------------===//

void HTMLDiagnostics::FlushDiagnosticsImpl(
  std::vector<const PathDiagnostic *> &Diags,
  FilesMade *filesMade) {
  for (const auto Diag : Diags)
    ReportDiag(*Diag, filesMade);
}

void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
                                 FilesMade *filesMade) {
  // Create the HTML directory if it is missing.
  if (!createdDir) {
    createdDir = true;
    if (std::error_code ec = llvm::sys::fs::create_directories(Directory)) {
      llvm::errs() << "warning: could not create directory '"
                   << Directory << "': " << ec.message() << '\n';
      noDir = true;
      return;
    }
  }

  if (noDir)
    return;

  // First flatten out the entire path to make it easier to use.
  PathPieces path = D.path.flatten(/*ShouldFlattenMacros=*/false);

  // The path as already been prechecked that the path is non-empty.
  assert(!path.empty());
  const SourceManager &SMgr = path.front()->getLocation().getManager();

  // Create a new rewriter to generate HTML.
  Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());

  // The file for the first path element is considered the main report file, it
  // will usually be equivalent to SMgr.getMainFileID(); however, it might be a
  // header when -analyzer-opt-analyze-headers is used.
  FileID ReportFile = path.front()->getLocation().asLocation().getExpansionLoc().getFileID();

  // Get the function/method name
  SmallString<128> declName("unknown");
  int offsetDecl = 0;
  if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
      if (const auto *ND = dyn_cast<NamedDecl>(DeclWithIssue))
          declName = ND->getDeclName().getAsString();

      if (const Stmt *Body = DeclWithIssue->getBody()) {
          // Retrieve the relative position of the declaration which will be used
          // for the file name
          FullSourceLoc L(
              SMgr.getExpansionLoc(path.back()->getLocation().asLocation()),
              SMgr);
          FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getBeginLoc()), SMgr);
          offsetDecl = L.getExpansionLineNumber() - FunL.getExpansionLineNumber();
      }
  }

  std::string report = GenerateHTML(D, R, SMgr, path, declName.c_str());
  if (report.empty()) {
    llvm::errs() << "warning: no diagnostics generated for main file.\n";
    return;
  }

  // Create a path for the target HTML file.
  int FD;
  SmallString<128> Model, ResultPath;

  if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
      llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
      if (std::error_code EC =
          llvm::sys::fs::make_absolute(Model)) {
          llvm::errs() << "warning: could not make '" << Model
                       << "' absolute: " << EC.message() << '\n';
        return;
      }
      if (std::error_code EC =
          llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
          llvm::errs() << "warning: could not create file in '" << Directory
                       << "': " << EC.message() << '\n';
          return;
      }
  } else {
      int i = 1;
      std::error_code EC;
      do {
          // Find a filename which is not already used
          const FileEntry* Entry = SMgr.getFileEntryForID(ReportFile);
          std::stringstream filename;
          Model = "";
          filename << "report-"
                   << llvm::sys::path::filename(Entry->getName()).str()
                   << "-" << declName.c_str()
                   << "-" << offsetDecl
                   << "-" << i << ".html";
          llvm::sys::path::append(Model, Directory,
                                  filename.str());
          EC = llvm::sys::fs::openFileForReadWrite(
              Model, FD, llvm::sys::fs::CD_CreateNew, llvm::sys::fs::OF_None);
          if (EC && EC != llvm::errc::file_exists) {
              llvm::errs() << "warning: could not create file '" << Model
                           << "': " << EC.message() << '\n';
              return;
          }
          i++;
      } while (EC);
  }

  llvm::raw_fd_ostream os(FD, true);

  if (filesMade)
    filesMade->addDiagnostic(D, getName(),
                             llvm::sys::path::filename(ResultPath));

  // Emit the HTML to disk.
  os << report;
}

std::string HTMLDiagnostics::GenerateHTML(const PathDiagnostic& D, Rewriter &R,
    const SourceManager& SMgr, const PathPieces& path, const char *declName) {
  // Rewrite source files as HTML for every new file the path crosses
  std::vector<FileID> FileIDs;
  for (auto I : path) {
    FileID FID = I->getLocation().asLocation().getExpansionLoc().getFileID();
    if (llvm::is_contained(FileIDs, FID))
      continue;

    FileIDs.push_back(FID);
    RewriteFile(R, path, FID);
  }

  if (SupportsCrossFileDiagnostics && FileIDs.size() > 1) {
    // Prefix file names, anchor tags, and nav cursors to every file
    for (auto I = FileIDs.begin(), E = FileIDs.end(); I != E; I++) {
      std::string s;
      llvm::raw_string_ostream os(s);

      if (I != FileIDs.begin())
        os << "<hr class=divider>\n";

      os << "<div id=File" << I->getHashValue() << ">\n";

      // Left nav arrow
      if (I != FileIDs.begin())
        os << "<div class=FileNav><a href=\"#File" << (I - 1)->getHashValue()
           << "\">&#x2190;</a></div>";

      os << "<h4 class=FileName>" << SMgr.getFileEntryForID(*I)->getName()
         << "</h4>\n";

      // Right nav arrow
      if (I + 1 != E)
        os << "<div class=FileNav><a href=\"#File" << (I + 1)->getHashValue()
           << "\">&#x2192;</a></div>";

      os << "</div>\n";

      R.InsertTextBefore(SMgr.getLocForStartOfFile(*I), os.str());
    }

    // Append files to the main report file in the order they appear in the path
    for (auto I : llvm::make_range(FileIDs.begin() + 1, FileIDs.end())) {
      std::string s;
      llvm::raw_string_ostream os(s);

      const RewriteBuffer *Buf = R.getRewriteBufferFor(I);
      for (auto BI : *Buf)
        os << BI;

      R.InsertTextAfter(SMgr.getLocForEndOfFile(FileIDs[0]), os.str());
    }
  }

  const RewriteBuffer *Buf = R.getRewriteBufferFor(FileIDs[0]);
  if (!Buf)
    return {};

  // Add CSS, header, and footer.
  FileID FID =
      path.back()->getLocation().asLocation().getExpansionLoc().getFileID();
  const FileEntry* Entry = SMgr.getFileEntryForID(FID);
  FinalizeHTML(D, R, SMgr, path, FileIDs[0], Entry, declName);

  std::string file;
  llvm::raw_string_ostream os(file);
  for (auto BI : *Buf)
    os << BI;

  return os.str();
}

void HTMLDiagnostics::dumpCoverageData(
    const PathDiagnostic &D,
    const PathPieces &path,
    llvm::raw_string_ostream &os) {

  const FilesToLineNumsMap &ExecutedLines = D.getExecutedLines();

  os << "var relevant_lines = {";
  for (auto I = ExecutedLines.begin(),
            E = ExecutedLines.end(); I != E; ++I) {
    if (I != ExecutedLines.begin())
      os << ", ";

    os << "\"" << I->first.getHashValue() << "\": {";
    for (unsigned LineNo : I->second) {
      if (LineNo != *(I->second.begin()))
        os << ", ";

      os << "\"" << LineNo << "\": 1";
    }
    os << "}";
  }

  os << "};";
}

std::string HTMLDiagnostics::showRelevantLinesJavascript(
      const PathDiagnostic &D, const PathPieces &path) {
  std::string s;
  llvm::raw_string_ostream os(s);
  os << "<script type='text/javascript'>\n";
  dumpCoverageData(D, path, os);
  os << R"<<<(

var filterCounterexample = function (hide) {
  var tables = document.getElementsByClassName("code");
  for (var t=0; t<tables.length; t++) {
    var table = tables[t];
    var file_id = table.getAttribute("data-fileid");
    var lines_in_fid = relevant_lines[file_id];
    if (!lines_in_fid) {
      lines_in_fid = {};
    }
    var lines = table.getElementsByClassName("codeline");
    for (var i=0; i<lines.length; i++) {
        var el = lines[i];
        var lineNo = el.getAttribute("data-linenumber");
        if (!lines_in_fid[lineNo]) {
          if (hide) {
            el.setAttribute("hidden", "");
          } else {
            el.removeAttribute("hidden");
          }
        }
    }
  }
}

window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return;
  }
  if (event.key == "S") {
    var checked = document.getElementsByName("showCounterexample")[0].checked;
    filterCounterexample(!checked);
    document.getElementsByName("showCounterexample")[0].checked = !checked;
  } else {
    return;
  }
  event.preventDefault();
}, true);

document.addEventListener("DOMContentLoaded", function() {
    document.querySelector('input[name="showCounterexample"]').onchange=
        function (event) {
      filterCounterexample(this.checked);
    };
});
</script>

<form>
    <input type="checkbox" name="showCounterexample" id="showCounterexample" />
    <label for="showCounterexample">
       Show only relevant lines
    </label>
</form>
)<<<";

  return os.str();
}

void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
    const SourceManager& SMgr, const PathPieces& path, FileID FID,
    const FileEntry *Entry, const char *declName) {
  // This is a cludge; basically we want to append either the full
  // working directory if we have no directory information.  This is
  // a work in progress.

  llvm::SmallString<0> DirName;

  if (llvm::sys::path::is_relative(Entry->getName())) {
    llvm::sys::fs::current_path(DirName);
    DirName += '/';
  }

  int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber();
  int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();

  R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), showHelpJavascript());

  R.InsertTextBefore(SMgr.getLocForStartOfFile(FID),
                     generateKeyboardNavigationJavascript());

  // Checkbox and javascript for filtering the output to the counterexample.
  R.InsertTextBefore(SMgr.getLocForStartOfFile(FID),
                     showRelevantLinesJavascript(D, path));

  // Add the name of the file as an <h1> tag.
  {
    std::string s;
    llvm::raw_string_ostream os(s);

    os << "<!-- REPORTHEADER -->\n"
       << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
          "<tr><td class=\"rowname\">File:</td><td>"
       << html::EscapeText(DirName)
       << html::EscapeText(Entry->getName())
       << "</td></tr>\n<tr><td class=\"rowname\">Warning:</td><td>"
          "<a href=\"#EndPath\">line "
       << LineNumber
       << ", column "
       << ColumnNumber
       << "</a><br />"
       << D.getVerboseDescription() << "</td></tr>\n";

    // The navigation across the extra notes pieces.
    unsigned NumExtraPieces = 0;
    for (const auto &Piece : path) {
      if (const auto *P = dyn_cast<PathDiagnosticNotePiece>(Piece.get())) {
        int LineNumber =
            P->getLocation().asLocation().getExpansionLineNumber();
        int ColumnNumber =
            P->getLocation().asLocation().getExpansionColumnNumber();
        os << "<tr><td class=\"rowname\">Note:</td><td>"
           << "<a href=\"#Note" << NumExtraPieces << "\">line "
           << LineNumber << ", column " << ColumnNumber << "</a><br />"
           << P->getString() << "</td></tr>";
        ++NumExtraPieces;
      }
    }

    // Output any other meta data.

    for (PathDiagnostic::meta_iterator I = D.meta_begin(), E = D.meta_end();
         I != E; ++I) {
      os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
    }

    os << R"<<<(
</table>
<!-- REPORTSUMMARYEXTRA -->
<h3>Annotated Source Code</h3>
<p>Press <a href="#" onclick="toggleHelp(); return false;">'?'</a>
   to see keyboard shortcuts</p>
<input type="checkbox" class="spoilerhider" id="showinvocation" />
<label for="showinvocation" >Show analyzer invocation</label>
<div class="spoiler">clang -cc1 )<<<";
    os << html::EscapeText(AnalyzerOpts.FullCompilerInvocation);
    os << R"<<<(
</div>
<div id='tooltiphint' hidden="true">
  <p>Keyboard shortcuts: </p>
  <ul>
    <li>Use 'j/k' keys for keyboard navigation</li>
    <li>Use 'Shift+S' to show/hide relevant lines</li>
    <li>Use '?' to toggle this window</li>
  </ul>
  <a href="#" onclick="toggleHelp(); return false;">Close</a>
</div>
)<<<";
    R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }

  // Embed meta-data tags.
  {
    std::string s;
    llvm::raw_string_ostream os(s);

    StringRef BugDesc = D.getVerboseDescription();
    if (!BugDesc.empty())
      os << "\n<!-- BUGDESC " << BugDesc << " -->\n";

    StringRef BugType = D.getBugType();
    if (!BugType.empty())
      os << "\n<!-- BUGTYPE " << BugType << " -->\n";

    PathDiagnosticLocation UPDLoc = D.getUniqueingLoc();
    FullSourceLoc L(SMgr.getExpansionLoc(UPDLoc.isValid()
                                             ? UPDLoc.asLocation()
                                             : D.getLocation().asLocation()),
                    SMgr);
    const Decl *DeclWithIssue = D.getDeclWithIssue();

    StringRef BugCategory = D.getCategory();
    if (!BugCategory.empty())
      os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";

    os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";

    os << "\n<!-- FILENAME " << llvm::sys::path::filename(Entry->getName()) << " -->\n";

    os  << "\n<!-- FUNCTIONNAME " <<  declName << " -->\n";

    os << "\n<!-- ISSUEHASHCONTENTOFLINEINCONTEXT "
       << GetIssueHash(SMgr, L, D.getCheckerName(), D.getBugType(),
                       DeclWithIssue, PP.getLangOpts())
       << " -->\n";

    os << "\n<!-- BUGLINE "
       << LineNumber
       << " -->\n";

    os << "\n<!-- BUGCOLUMN "
      << ColumnNumber
      << " -->\n";

    os << "\n<!-- BUGPATHLENGTH " << path.size() << " -->\n";

    // Mark the end of the tags.
    os << "\n<!-- BUGMETAEND -->\n";

    // Insert the text.
    R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }

  html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
}

StringRef HTMLDiagnostics::showHelpJavascript() {
  return R"<<<(
<script type='text/javascript'>

var toggleHelp = function() {
    var hint = document.querySelector("#tooltiphint");
    var attributeName = "hidden";
    if (hint.hasAttribute(attributeName)) {
      hint.removeAttribute(attributeName);
    } else {
      hint.setAttribute("hidden", "true");
    }
};
window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return;
  }
  if (event.key == "?") {
    toggleHelp();
  } else {
    return;
  }
  event.preventDefault();
});
</script>
)<<<";
}

static void
HandlePopUpPieceStartTag(Rewriter &R,
                         const std::vector<SourceRange> &PopUpRanges) {
  for (const auto &Range : PopUpRanges) {
    html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "",
                         "<table class='variable_popup'><tbody>",
                         /*IsTokenRange=*/true);
  }
}

static void HandlePopUpPieceEndTag(Rewriter &R,
                                   const PathDiagnosticPopUpPiece &Piece,
                                   std::vector<SourceRange> &PopUpRanges,
                                   unsigned int LastReportedPieceIndex,
                                   unsigned int PopUpPieceIndex) {
  SmallString<256> Buf;
  llvm::raw_svector_ostream Out(Buf);

  SourceRange Range(Piece.getLocation().asRange());

  // Write out the path indices with a right arrow and the message as a row.
  Out << "<tr><td valign='top'><div class='PathIndex PathIndexPopUp'>"
      << LastReportedPieceIndex;

  // Also annotate the state transition with extra indices.
  Out << '.' << PopUpPieceIndex;

  Out << "</div></td><td>" << Piece.getString() << "</td></tr>";

  // If no report made at this range mark the variable and add the end tags.
  if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) ==
      PopUpRanges.end()) {
    // Store that we create a report at this range.
    PopUpRanges.push_back(Range);

    Out << "</tbody></table></span>";
    html::HighlightRange(R, Range.getBegin(), Range.getEnd(),
                         "<span class='variable'>", Buf.c_str(),
                         /*IsTokenRange=*/true);
  } else {
    // Otherwise inject just the new row at the end of the range.
    html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "", Buf.c_str(),
                         /*IsTokenRange=*/true);
  }
}

void HTMLDiagnostics::RewriteFile(Rewriter &R,
                                  const PathPieces& path, FileID FID) {
  // Process the path.
  // Maintain the counts of extra note pieces separately.
  unsigned TotalPieces = path.size();
  unsigned TotalNotePieces = std::count_if(
      path.begin(), path.end(), [](const PathDiagnosticPieceRef &p) {
        return isa<PathDiagnosticNotePiece>(*p);
      });
  unsigned PopUpPieceCount = std::count_if(
      path.begin(), path.end(), [](const PathDiagnosticPieceRef &p) {
        return isa<PathDiagnosticPopUpPiece>(*p);
      });

  unsigned TotalRegularPieces = TotalPieces - TotalNotePieces - PopUpPieceCount;
  unsigned NumRegularPieces = TotalRegularPieces;
  unsigned NumNotePieces = TotalNotePieces;
  // Stores the count of the regular piece indices.
  std::map<int, int> IndexMap;

  // Stores the different ranges where we have reported something.
  std::vector<SourceRange> PopUpRanges;
  for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
    const auto &Piece = *I->get();

    if (isa<PathDiagnosticPopUpPiece>(Piece)) {
      ++IndexMap[NumRegularPieces];
    } else if (isa<PathDiagnosticNotePiece>(Piece)) {
      // This adds diagnostic bubbles, but not navigation.
      // Navigation through note pieces would be added later,
      // as a separate pass through the piece list.
      HandlePiece(R, FID, Piece, PopUpRanges, NumNotePieces, TotalNotePieces);
      --NumNotePieces;
    } else {
      HandlePiece(R, FID, Piece, PopUpRanges, NumRegularPieces,
                  TotalRegularPieces);
      --NumRegularPieces;
    }
  }

  // Secondary indexing if we are having multiple pop-ups between two notes.
  // (e.g. [(13) 'a' is 'true'];  [(13.1) 'b' is 'false'];  [(13.2) 'c' is...)
  NumRegularPieces = TotalRegularPieces;
  for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
    const auto &Piece = *I->get();

    if (const auto *PopUpP = dyn_cast<PathDiagnosticPopUpPiece>(&Piece)) {
      int PopUpPieceIndex = IndexMap[NumRegularPieces];

      // Pop-up pieces needs the index of the last reported piece and its count
      // how many times we report to handle multiple reports on the same range.
      // This marks the variable, adds the </table> end tag and the message
      // (list element) as a row. The <table> start tag will be added after the
      // rows has been written out. Note: It stores every different range.
      HandlePopUpPieceEndTag(R, *PopUpP, PopUpRanges, NumRegularPieces,
                             PopUpPieceIndex);

      if (PopUpPieceIndex > 0)
        --IndexMap[NumRegularPieces];

    } else if (!isa<PathDiagnosticNotePiece>(Piece)) {
      --NumRegularPieces;
    }
  }

  // Add the <table> start tag of pop-up pieces based on the stored ranges.
  HandlePopUpPieceStartTag(R, PopUpRanges);

  // Add line numbers, header, footer, etc.
  html::EscapeText(R, FID);
  html::AddLineNumbers(R, FID);

  // If we have a preprocessor, relex the file and syntax highlight.
  // We might not have a preprocessor if we come from a deserialized AST file,
  // for example.
  html::SyntaxHighlight(R, FID, PP);
  html::HighlightMacros(R, FID, PP);
}

void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID,
                                  const PathDiagnosticPiece &P,
                                  const std::vector<SourceRange> &PopUpRanges,
                                  unsigned num, unsigned max) {
  // For now, just draw a box above the line in question, and emit the
  // warning.
  FullSourceLoc Pos = P.getLocation().asLocation();

  if (!Pos.isValid())
    return;

  SourceManager &SM = R.getSourceMgr();
  assert(&Pos.getManager() == &SM && "SourceManagers are different!");
  std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos);

  if (LPosInfo.first != BugFileID)
    return;

  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
  const char* FileStart = Buf->getBufferStart();

  // Compute the column number.  Rewind from the current position to the start
  // of the line.
  unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
  const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData();
  const char *LineStart = TokInstantiationPtr-ColNo;

  // Compute LineEnd.
  const char *LineEnd = TokInstantiationPtr;
  const char* FileEnd = Buf->getBufferEnd();
  while (*LineEnd != '\n' && LineEnd != FileEnd)
    ++LineEnd;

  // Compute the margin offset by counting tabs and non-tabs.
  unsigned PosNo = 0;
  for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
    PosNo += *c == '\t' ? 8 : 1;

  // Create the html for the message.

  const char *Kind = nullptr;
  bool IsNote = false;
  bool SuppressIndex = (max == 1);
  switch (P.getKind()) {
  case PathDiagnosticPiece::Event: Kind = "Event"; break;
  case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
    // Setting Kind to "Control" is intentional.
  case PathDiagnosticPiece::Macro: Kind = "Control"; break;
  case PathDiagnosticPiece::Note:
    Kind = "Note";
    IsNote = true;
    SuppressIndex = true;
    break;
  case PathDiagnosticPiece::Call:
  case PathDiagnosticPiece::PopUp:
    llvm_unreachable("Calls and extra notes should already be handled");
  }

  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);

  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";

  if (IsNote)
    os << "Note" << num;
  else if (num == max)
    os << "EndPath";
  else
    os << "Path" << num;

  os << "\" class=\"msg";
  if (Kind)
    os << " msg" << Kind;
  os << "\" style=\"margin-left:" << PosNo << "ex";

  // Output a maximum size.
  if (!isa<PathDiagnosticMacroPiece>(P)) {
    // Get the string and determining its maximum substring.
    const auto &Msg = P.getString();
    unsigned max_token = 0;
    unsigned cnt = 0;
    unsigned len = Msg.size();

    for (char C : Msg)
      switch (C) {
      default:
        ++cnt;
        continue;
      case ' ':
      case '\t':
      case '\n':
        if (cnt > max_token) max_token = cnt;
        cnt = 0;
      }

    if (cnt > max_token)
      max_token = cnt;

    // Determine the approximate size of the message bubble in em.
    unsigned em;
    const unsigned max_line = 120;

    if (max_token >= max_line)
      em = max_token / 2;
    else {
      unsigned characters = max_line;
      unsigned lines = len / max_line;

      if (lines > 0) {
        for (; characters > max_token; --characters)
          if (len / characters > lines) {
            ++characters;
            break;
          }
      }

      em = characters / 2;
    }

    if (em < max_line/2)
      os << "; max-width:" << em << "em";
  }
  else
    os << "; max-width:100em";

  os << "\">";

  if (!SuppressIndex) {
    os << "<table class=\"msgT\"><tr><td valign=\"top\">";
    os << "<div class=\"PathIndex";
    if (Kind) os << " PathIndex" << Kind;
    os << "\">" << num << "</div>";

    if (num > 1) {
      os << "</td><td><div class=\"PathNav\"><a href=\"#Path"
         << (num - 1)
         << "\" title=\"Previous event ("
         << (num - 1)
         << ")\">&#x2190;</a></div></td>";
    }

    os << "</td><td>";
  }

  if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(&P)) {
    os << "Within the expansion of the macro '";

    // Get the name of the macro by relexing it.
    {
      FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc();
      assert(L.isFileID());
      StringRef BufferInfo = L.getBufferData();
      std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc();
      const char* MacroName = LocInfo.second + BufferInfo.data();
      Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(),
                     BufferInfo.begin(), MacroName, BufferInfo.end());

      Token TheTok;
      rawLexer.LexFromRawLexer(TheTok);
      for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
        os << MacroName[i];
    }

    os << "':\n";

    if (!SuppressIndex) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
        << (num + 1)
        << ")\">&#x2192;</a></div></td>";
      }

      os << "</tr></table>";
    }

    // Within a macro piece.  Write out each event.
    ProcessMacroPiece(os, *MP, 0);
  }
  else {
    os << html::EscapeText(P.getString());

    if (!SuppressIndex) {
      os << "</td>";
      if (num < max) {
        os << "<td><div class=\"PathNav\"><a href=\"#";
        if (num == max - 1)
          os << "EndPath";
        else
          os << "Path" << (num + 1);
        os << "\" title=\"Next event ("
           << (num + 1)
           << ")\">&#x2192;</a></div></td>";
      }

      os << "</tr></table>";
    }
  }

  os << "</div></td></tr>";

  // Insert the new html.
  unsigned DisplayPos = LineEnd - FileStart;
  SourceLocation Loc =
    SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos);

  R.InsertTextBefore(Loc, os.str());

  // Now highlight the ranges.
  ArrayRef<SourceRange> Ranges = P.getRanges();
  for (const auto &Range : Ranges) {
    // If we have already highlighted the range as a pop-up there is no work.
    if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) !=
        PopUpRanges.end())
      continue;

    HighlightRange(R, LPosInfo.first, Range);
  }
}

static void EmitAlphaCounter(raw_ostream &os, unsigned n) {
  unsigned x = n % ('z' - 'a');
  n /= 'z' - 'a';

  if (n > 0)
    EmitAlphaCounter(os, n);

  os << char('a' + x);
}

unsigned HTMLDiagnostics::ProcessMacroPiece(raw_ostream &os,
                                            const PathDiagnosticMacroPiece& P,
                                            unsigned num) {
  for (const auto &subPiece : P.subPieces) {
    if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(subPiece.get())) {
      num = ProcessMacroPiece(os, *MP, num);
      continue;
    }

    if (const auto *EP = dyn_cast<PathDiagnosticEventPiece>(subPiece.get())) {
      os << "<div class=\"msg msgEvent\" style=\"width:94%; "
            "margin-left:5px\">"
            "<table class=\"msgT\"><tr>"
            "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">";
      EmitAlphaCounter(os, num++);
      os << "</div></td><td valign=\"top\">"
         << html::EscapeText(EP->getString())
         << "</td></tr></table></div>\n";
    }
  }

  return num;
}

void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
                                     SourceRange Range,
                                     const char *HighlightStart,
                                     const char *HighlightEnd) {
  SourceManager &SM = R.getSourceMgr();
  const LangOptions &LangOpts = R.getLangOpts();

  SourceLocation InstantiationStart = SM.getExpansionLoc(Range.getBegin());
  unsigned StartLineNo = SM.getExpansionLineNumber(InstantiationStart);

  SourceLocation InstantiationEnd = SM.getExpansionLoc(Range.getEnd());
  unsigned EndLineNo = SM.getExpansionLineNumber(InstantiationEnd);

  if (EndLineNo < StartLineNo)
    return;

  if (SM.getFileID(InstantiationStart) != BugFileID ||
      SM.getFileID(InstantiationEnd) != BugFileID)
    return;

  // Compute the column number of the end.
  unsigned EndColNo = SM.getExpansionColumnNumber(InstantiationEnd);
  unsigned OldEndColNo = EndColNo;

  if (EndColNo) {
    // Add in the length of the token, so that we cover multi-char tokens.
    EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
  }

  // Highlight the range.  Make the span tag the outermost tag for the
  // selected range.

  SourceLocation E =
    InstantiationEnd.getLocWithOffset(EndColNo - OldEndColNo);

  html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
}

StringRef HTMLDiagnostics::generateKeyboardNavigationJavascript() {
  return R"<<<(
<script type='text/javascript'>
var digitMatcher = new RegExp("[0-9]+");

document.addEventListener("DOMContentLoaded", function() {
    document.querySelectorAll(".PathNav > a").forEach(
        function(currentValue, currentIndex) {
            var hrefValue = currentValue.getAttribute("href");
            currentValue.onclick = function() {
                scrollTo(document.querySelector(hrefValue));
                return false;
            };
        });
});

var findNum = function() {
    var s = document.querySelector(".selected");
    if (!s || s.id == "EndPath") {
        return 0;
    }
    var out = parseInt(digitMatcher.exec(s.id)[0]);
    return out;
};

var scrollTo = function(el) {
    document.querySelectorAll(".selected").forEach(function(s) {
        s.classList.remove("selected");
    });
    el.classList.add("selected");
    window.scrollBy(0, el.getBoundingClientRect().top -
        (window.innerHeight / 2));
}

var move = function(num, up, numItems) {
  if (num == 1 && up || num == numItems - 1 && !up) {
    return 0;
  } else if (num == 0 && up) {
    return numItems - 1;
  } else if (num == 0 && !up) {
    return 1 % numItems;
  }
  return up ? num - 1 : num + 1;
}

var numToId = function(num) {
  if (num == 0) {
    return document.getElementById("EndPath")
  }
  return document.getElementById("Path" + num);
};

var navigateTo = function(up) {
  var numItems = document.querySelectorAll(
      ".line > .msgEvent, .line > .msgControl").length;
  var currentSelected = findNum();
  var newSelected = move(currentSelected, up, numItems);
  var newEl = numToId(newSelected, numItems);

  // Scroll element into center.
  scrollTo(newEl);
};

window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return;
  }
  if (event.key == "j") {
    navigateTo(/*up=*/false);
  } else if (event.key == "k") {
    navigateTo(/*up=*/true);
  } else {
    return;
  }
  event.preventDefault();
}, true);
</script>
  )<<<";
}
