//===-- HTMLLogger.cpp ----------------------------------------------------===//
//
// 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 implements the HTML logger. Given a directory dir/, we write
// dir/0.html for the first analysis, etc.
// These files contain a visualization that allows inspecting the CFG and the
// state of the analysis at each point.
// Static assets (HTMLLogger.js, HTMLLogger.css) and SVG graphs etc are embedded
// so each output file is self-contained.
//
// VIEWS
//
// The timeline and function view are always shown. These allow selecting basic
// blocks, statements within them, and processing iterations (BBs are visited
// multiple times when e.g. loops are involved).
// These are written directly into the HTML body.
//
// There are also listings of particular basic blocks, and dumps of the state
// at particular analysis points (i.e. BB2 iteration 3 statement 2).
// These are only shown when the relevant BB/analysis point is *selected*.
//
// DATA AND TEMPLATES
//
// The HTML proper is mostly static.
// The analysis data is in a JSON object HTMLLoggerData which is embedded as
// a <script> in the <head>.
// This gets rendered into DOM by a simple template processor which substitutes
// the data into <template> tags embedded in the HTML. (see inflate() in JS).
//
// SELECTION
//
// This is the only real interactive mechanism.
//
// At any given time, there are several named selections, e.g.:
//   bb: B2               (basic block 0 is selected)
//   elt: B2.4            (statement 4 is selected)
//   iter: B2:1           (iteration 1 of the basic block is selected)
//   hover: B3            (hovering over basic block 3)
//
// The selection is updated by mouse events: hover by moving the mouse and
// others by clicking. Elements that are click targets generally have attributes
// (id or data-foo) that define what they should select.
// See watchSelection() in JS for the exact logic.
//
// When the "bb" selection is set to "B2":
//   - sections <section data-selection="bb"> get shown
//   - templates under such sections get re-rendered
//   - elements with class/id "B2" get class "bb-select"
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/FlowSensitive/AdornedCFG.h"
#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Logger.h"
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
// Defines assets: HTMLLogger_{html_js,css}
#include "HTMLLogger.inc"

namespace clang::dataflow {
namespace {

// Render a graphviz graph specification to SVG using the `dot` tool.
llvm::Expected<std::string> renderSVG(llvm::StringRef DotGraph);

using StreamFactory = std::function<std::unique_ptr<llvm::raw_ostream>()>;

// Recursively dumps Values/StorageLocations as JSON
class ModelDumper {
public:
  ModelDumper(llvm::json::OStream &JOS, const Environment &Env)
      : JOS(JOS), Env(Env) {}

  void dump(Value &V) {
    JOS.attribute("value_id", llvm::to_string(&V));
    if (!Visited.insert(&V).second)
      return;

    JOS.attribute("kind", debugString(V.getKind()));

    switch (V.getKind()) {
    case Value::Kind::Integer:
    case Value::Kind::TopBool:
    case Value::Kind::AtomicBool:
    case Value::Kind::FormulaBool:
      break;
    case Value::Kind::Pointer:
      JOS.attributeObject(
          "pointee", [&] { dump(cast<PointerValue>(V).getPointeeLoc()); });
      break;
    }

    for (const auto& Prop : V.properties())
      JOS.attributeObject(("p:" + Prop.first()).str(),
                          [&] { dump(*Prop.second); });

    // Running the SAT solver is expensive, but knowing which booleans are
    // guaranteed true/false here is valuable and hard to determine by hand.
    if (auto *B = llvm::dyn_cast<BoolValue>(&V)) {
      JOS.attribute("formula", llvm::to_string(B->formula()));
      JOS.attribute("truth", Env.proves(B->formula()) ? "true"
                             : Env.proves(Env.arena().makeNot(B->formula()))
                                 ? "false"
                                 : "unknown");
    }
  }
  void dump(const StorageLocation &L) {
    JOS.attribute("location", llvm::to_string(&L));
    if (!Visited.insert(&L).second)
      return;

    JOS.attribute("type", L.getType().getAsString());
    if (!L.getType()->isRecordType())
      if (auto *V = Env.getValue(L))
        dump(*V);

    if (auto *RLoc = dyn_cast<RecordStorageLocation>(&L)) {
      for (const auto &Child : RLoc->children())
        JOS.attributeObject("f:" + Child.first->getNameAsString(), [&] {
          if (Child.second)
            dump(*Child.second);
        });

      for (const auto &SyntheticField : RLoc->synthetic_fields())
        JOS.attributeObject(("sf:" + SyntheticField.first()).str(),
                            [&] { dump(*SyntheticField.second); });
    }
  }

  llvm::DenseSet<const void*> Visited;
  llvm::json::OStream &JOS;
  const Environment &Env;
};

class HTMLLogger : public Logger {
  struct Iteration {
    const CFGBlock *Block;
    unsigned Iter;
    bool PostVisit;
    bool Converged;
  };

  StreamFactory Streams;
  std::unique_ptr<llvm::raw_ostream> OS;
  std::string JSON;
  llvm::raw_string_ostream JStringStream{JSON};
  llvm::json::OStream JOS{JStringStream, /*Indent=*/2};

  const AdornedCFG *ACFG;
  // Timeline of iterations of CFG block visitation.
  std::vector<Iteration> Iters;
  // Indexes  in `Iters` of the iterations for each block.
  llvm::DenseMap<const CFGBlock *, llvm::SmallVector<size_t>> BlockIters;
  // For a given block ID, did the block converge (on the last iteration)?
  llvm::BitVector BlockConverged;
  // The messages logged in the current context but not yet written.
  std::string ContextLogs;
  // The number of elements we have visited within the current CFG block.
  unsigned ElementIndex;

public:
  explicit HTMLLogger(StreamFactory Streams) : Streams(std::move(Streams)) {}
  void beginAnalysis(const AdornedCFG &ACFG,
                     TypeErasedDataflowAnalysis &A) override {
    OS = Streams();
    this->ACFG = &ACFG;
    *OS << llvm::StringRef(HTMLLogger_html).split("<?INJECT?>").first;

    BlockConverged.resize(ACFG.getCFG().getNumBlockIDs());

    const auto &D = ACFG.getDecl();
    const auto &SM = A.getASTContext().getSourceManager();
    *OS << "<title>";
    if (const auto *ND = dyn_cast<NamedDecl>(&D))
      *OS << ND->getNameAsString() << " at ";
    *OS << SM.getFilename(D.getLocation()) << ":"
        << SM.getSpellingLineNumber(D.getLocation());
    *OS << "</title>\n";

    *OS << "<style>" << HTMLLogger_css << "</style>\n";
    *OS << "<script>" << HTMLLogger_js << "</script>\n";

    writeCode();
    JOS.objectBegin();
    JOS.attributeBegin("states");
    JOS.objectBegin();
  }
  // Between beginAnalysis() and endAnalysis() we write all the states for
  // particular analysis points into the `timeline` array.
  void endAnalysis() override {
    JOS.objectEnd();
    JOS.attributeEnd();

    JOS.attributeArray("timeline", [&] {
      for (const auto &E : Iters) {
        JOS.object([&] {
          JOS.attribute("block", blockID(E.Block->getBlockID()));
          JOS.attribute("iter", E.Iter);
          JOS.attribute("post_visit", E.PostVisit);
          JOS.attribute("converged", E.Converged);
        });
      }
    });
    JOS.attributeObject("cfg", [&] {
      for (const auto &E : BlockIters)
        writeBlock(*E.first, E.second);
    });

    JOS.objectEnd();

    writeCFG();

    *OS << "<script>var HTMLLoggerData = \n";
    *OS << JSON;
    *OS << ";\n</script>\n";
    *OS << llvm::StringRef(HTMLLogger_html).split("<?INJECT?>").second;
  }

  void enterBlock(const CFGBlock &B, bool PostVisit) override {
    llvm::SmallVector<size_t> &BIter = BlockIters[&B];
    unsigned IterNum = BIter.size() + 1;
    BIter.push_back(Iters.size());
    Iters.push_back({&B, IterNum, PostVisit, /*Converged=*/false});
    if (!PostVisit)
      BlockConverged[B.getBlockID()] = false;
    ElementIndex = 0;
  }
  void enterElement(const CFGElement &E) override {
    ++ElementIndex;
  }

  static std::string blockID(unsigned Block) {
    return llvm::formatv("B{0}", Block);
  }
  static std::string eltID(unsigned Block, unsigned Element) {
    return llvm::formatv("B{0}.{1}", Block, Element);
  }
  static std::string iterID(unsigned Block, unsigned Iter) {
    return llvm::formatv("B{0}:{1}", Block, Iter);
  }
  static std::string elementIterID(unsigned Block, unsigned Iter,
                                   unsigned Element) {
    return llvm::formatv("B{0}:{1}_B{0}.{2}", Block, Iter, Element);
  }

  // Write the analysis state associated with a particular analysis point.
  // FIXME: this dump is fairly opaque. We should show:
  //  - values associated with the current Stmt
  //  - values associated with its children
  //  - meaningful names for values
  //  - which boolean values are implied true/false by the flow condition
  void recordState(TypeErasedDataflowAnalysisState &State) override {
    unsigned Block = Iters.back().Block->getBlockID();
    unsigned Iter = Iters.back().Iter;
    bool PostVisit = Iters.back().PostVisit;
    JOS.attributeObject(elementIterID(Block, Iter, ElementIndex), [&] {
      JOS.attribute("block", blockID(Block));
      JOS.attribute("iter", Iter);
      JOS.attribute("post_visit", PostVisit);
      JOS.attribute("element", ElementIndex);

      // If this state immediately follows an Expr, show its built-in model.
      if (ElementIndex > 0) {
        auto S =
            Iters.back().Block->Elements[ElementIndex - 1].getAs<CFGStmt>();
        if (const Expr *E = S ? llvm::dyn_cast<Expr>(S->getStmt()) : nullptr) {
          if (E->isPRValue()) {
            if (!E->getType()->isRecordType())
              if (auto *V = State.Env.getValue(*E))
                JOS.attributeObject(
                    "value", [&] { ModelDumper(JOS, State.Env).dump(*V); });
          } else {
            if (auto *Loc = State.Env.getStorageLocation(*E))
              JOS.attributeObject(
                  "value", [&] { ModelDumper(JOS, State.Env).dump(*Loc); });
          }
        }
      }
      if (!ContextLogs.empty()) {
        JOS.attribute("logs", ContextLogs);
        ContextLogs.clear();
      }
      {
        std::string BuiltinLattice;
        llvm::raw_string_ostream BuiltinLatticeS(BuiltinLattice);
        State.Env.dump(BuiltinLatticeS);
        JOS.attribute("builtinLattice", BuiltinLattice);
      }
    });
  }
  void blockConverged() override {
    Iters.back().Converged = true;
    BlockConverged[Iters.back().Block->getBlockID()] = true;
  }

  void logText(llvm::StringRef S) override {
    ContextLogs.append(S.begin(), S.end());
    ContextLogs.push_back('\n');
  }

private:
  // Write the CFG block details.
  // Currently this is just the list of elements in execution order.
  // FIXME: an AST dump would be a useful view, too.
  void writeBlock(const CFGBlock &B, llvm::ArrayRef<size_t> ItersForB) {
    JOS.attributeObject(blockID(B.getBlockID()), [&] {
      JOS.attributeArray("iters", [&] {
        for (size_t IterIdx : ItersForB) {
          const Iteration &Iter = Iters[IterIdx];
          JOS.object([&] {
            JOS.attribute("iter", Iter.Iter);
            JOS.attribute("post_visit", Iter.PostVisit);
            JOS.attribute("converged", Iter.Converged);
          });
        }
      });
      JOS.attributeArray("elements", [&] {
        for (const auto &Elt : B.Elements) {
          std::string Dump;
          llvm::raw_string_ostream DumpS(Dump);
          Elt.dumpToStream(DumpS);
          JOS.value(Dump);
        }
      });
    });
  }

  // Write the code of function being examined.
  // We want to overlay the code with <span>s that mark which BB particular
  // tokens are associated with, and even which BB element (so that clicking
  // can select the right element).
  void writeCode() {
    const auto &AST = ACFG->getDecl().getASTContext();
    bool Invalid = false;

    // Extract the source code from the original file.
    // Pretty-printing from the AST would probably be nicer (no macros or
    // indentation to worry about), but we need the boundaries of particular
    // AST nodes and the printer doesn't provide this.
    auto Range = clang::Lexer::makeFileCharRange(
        CharSourceRange::getTokenRange(ACFG->getDecl().getSourceRange()),
        AST.getSourceManager(), AST.getLangOpts());
    if (Range.isInvalid())
      return;
    llvm::StringRef Code = clang::Lexer::getSourceText(
        Range, AST.getSourceManager(), AST.getLangOpts(), &Invalid);
    if (Invalid)
      return;

    // TokenInfo stores the BB and set of elements that a token is part of.
    struct TokenInfo {
      enum : unsigned { Missing = static_cast<unsigned>(-1) };

      // The basic block this is part of.
      // This is the BB of the stmt with the smallest containing range.
      unsigned BB = Missing;
      unsigned BBPriority = 0;
      // The most specific stmt this is part of (smallest range).
      unsigned Elt = Missing;
      unsigned EltPriority = 0;
      // All stmts this is part of.
      SmallVector<unsigned> Elts;

      // Mark this token as being part of BB.Elt.
      // RangeLen is the character length of the element's range, used to
      // distinguish inner vs outer statements.
      // For example in `a==0`, token "a" is part of the stmts "a" and "a==0".
      // However "a" has a smaller range, so is more specific. Clicking on the
      // token "a" should select the stmt "a".
      void assign(unsigned BB, unsigned Elt, unsigned RangeLen) {
        // A worse BB (larger range) => ignore.
        if (this->BB != Missing && BB != this->BB && BBPriority <= RangeLen)
          return;
        if (BB != this->BB) {
          this->BB = BB;
          Elts.clear();
          BBPriority = RangeLen;
        }
        BBPriority = std::min(BBPriority, RangeLen);
        Elts.push_back(Elt);
        if (this->Elt == Missing || EltPriority > RangeLen)
          this->Elt = Elt;
      }
      bool operator==(const TokenInfo &Other) const {
        return std::tie(BB, Elt, Elts) ==
               std::tie(Other.BB, Other.Elt, Other.Elts);
      }
      // Write the attributes for the <span> on this token.
      void write(llvm::raw_ostream &OS) const {
        OS << "class='c";
        if (BB != Missing)
          OS << " " << blockID(BB);
        for (unsigned Elt : Elts)
          OS << " " << eltID(BB, Elt);
        OS << "'";

        if (Elt != Missing)
          OS << " data-elt='" << eltID(BB, Elt) << "'";
        if (BB != Missing)
          OS << " data-bb='" << blockID(BB) << "'";
      }
    };

    // Construct one TokenInfo per character in a flat array.
    // This is inefficient (chars in a token all have the same info) but simple.
    std::vector<TokenInfo> State(Code.size());
    for (const auto *Block : ACFG->getCFG()) {
      unsigned EltIndex = 0;
      for (const auto& Elt : *Block) {
        ++EltIndex;
        if (const auto S = Elt.getAs<CFGStmt>()) {
          auto EltRange = clang::Lexer::makeFileCharRange(
              CharSourceRange::getTokenRange(S->getStmt()->getSourceRange()),
              AST.getSourceManager(), AST.getLangOpts());
          if (EltRange.isInvalid())
            continue;
          if (EltRange.getBegin() < Range.getBegin() ||
              EltRange.getEnd() >= Range.getEnd() ||
              EltRange.getEnd() < Range.getBegin() ||
              EltRange.getEnd() >= Range.getEnd())
            continue;
          unsigned Off = EltRange.getBegin().getRawEncoding() -
                         Range.getBegin().getRawEncoding();
          unsigned Len = EltRange.getEnd().getRawEncoding() -
                         EltRange.getBegin().getRawEncoding();
          for (unsigned I = 0; I < Len; ++I)
            State[Off + I].assign(Block->getBlockID(), EltIndex, Len);
        }
      }
    }

    // Finally, write the code with the correct <span>s.
    unsigned Line =
        AST.getSourceManager().getSpellingLineNumber(Range.getBegin());
    *OS << "<template data-copy='code'>\n";
    *OS << "<code class='filename'>";
    llvm::printHTMLEscaped(
        llvm::sys::path::filename(
            AST.getSourceManager().getFilename(Range.getBegin())),
        *OS);
    *OS << "</code>";
    *OS << "<code class='line' data-line='" << Line++ << "'>";
    for (unsigned I = 0; I < Code.size(); ++I) {
      // Don't actually write a <span> around each character, only break spans
      // when the TokenInfo changes.
      bool NeedOpen = I == 0 || !(State[I] == State[I-1]);
      bool NeedClose = I + 1 == Code.size() || !(State[I] == State[I + 1]);
      if (NeedOpen) {
        *OS << "<span ";
        State[I].write(*OS);
        *OS << ">";
      }
      if (Code[I] == '\n')
        *OS << "</code>\n<code class='line' data-line='" << Line++ << "'>";
      else
        llvm::printHTMLEscaped(Code.substr(I, 1), *OS);
      if (NeedClose) *OS << "</span>";
    }
    *OS << "</code>\n";
    *OS << "</template>";
  }

  // Write the CFG diagram, a graph of basic blocks.
  // Laying out graphs is hard, so we construct a graphviz description and shell
  // out to `dot` to turn it into an SVG.
  void writeCFG() {
    *OS << "<template data-copy='cfg'>\n";
    if (auto SVG = renderSVG(buildCFGDot(ACFG->getCFG())))
      *OS << *SVG;
    else
      *OS << "Can't draw CFG: " << toString(SVG.takeError());
    *OS << "</template>\n";
  }

  // Produce a graphviz description of a CFG.
  std::string buildCFGDot(const clang::CFG &CFG) {
    std::string Graph;
    llvm::raw_string_ostream GraphS(Graph);
    // Graphviz likes to add unhelpful tooltips everywhere, " " suppresses.
    GraphS << R"(digraph {
      tooltip=" "
      node[class=bb, shape=square, fontname="sans-serif", tooltip=" "]
      edge[tooltip = " "]
)";
    for (unsigned I = 0; I < CFG.getNumBlockIDs(); ++I) {
      std::string Name = blockID(I);
      // Rightwards arrow, vertical line
      const char *ConvergenceMarker = (const char *)u8"\\n\u2192\u007c";
      if (BlockConverged[I])
        Name += ConvergenceMarker;
      GraphS << "  " << blockID(I) << " [id=" << blockID(I) << " label=\""
             << Name << "\"]\n";
    }
    for (const auto *Block : CFG) {
      for (const auto &Succ : Block->succs()) {
        if (Succ.getReachableBlock())
          GraphS << "  " << blockID(Block->getBlockID()) << " -> "
                 << blockID(Succ.getReachableBlock()->getBlockID()) << "\n";
      }
    }
    GraphS << "}\n";
    return Graph;
  }
};

// Nothing interesting here, just subprocess/temp-file plumbing.
llvm::Expected<std::string> renderSVG(llvm::StringRef DotGraph) {
  std::string DotPath;
  if (const auto *FromEnv = ::getenv("GRAPHVIZ_DOT"))
    DotPath = FromEnv;
  else {
    auto FromPath = llvm::sys::findProgramByName("dot");
    if (!FromPath)
      return llvm::createStringError(FromPath.getError(),
                                     "'dot' not found on PATH");
    DotPath = FromPath.get();
  }

  // Create input and output files for `dot` subprocess.
  // (We create the output file as empty, to reserve the temp filename).
  llvm::SmallString<256> Input, Output;
  int InputFD;
  if (auto EC = llvm::sys::fs::createTemporaryFile("analysis", ".dot", InputFD,
                                                   Input))
    return llvm::createStringError(EC, "failed to create `dot` temp input");
  llvm::raw_fd_ostream(InputFD, /*shouldClose=*/true) << DotGraph;
  auto DeleteInput =
      llvm::make_scope_exit([&] { llvm::sys::fs::remove(Input); });
  if (auto EC = llvm::sys::fs::createTemporaryFile("analysis", ".svg", Output))
    return llvm::createStringError(EC, "failed to create `dot` temp output");
  auto DeleteOutput =
      llvm::make_scope_exit([&] { llvm::sys::fs::remove(Output); });

  std::vector<std::optional<llvm::StringRef>> Redirects = {
      Input, Output,
      /*stderr=*/std::nullopt};
  std::string ErrMsg;
  int Code = llvm::sys::ExecuteAndWait(
      DotPath, {"dot", "-Tsvg"}, /*Env=*/std::nullopt, Redirects,
      /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
  if (!ErrMsg.empty())
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "'dot' failed: " + ErrMsg);
  if (Code != 0)
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "'dot' failed (" + llvm::Twine(Code) + ")");

  auto Buf = llvm::MemoryBuffer::getFile(Output);
  if (!Buf)
    return llvm::createStringError(Buf.getError(), "Can't read `dot` output");

  // Output has <?xml> prefix we don't want. Skip to <svg> tag.
  llvm::StringRef Result = Buf.get()->getBuffer();
  auto Pos = Result.find("<svg");
  if (Pos == llvm::StringRef::npos)
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "Can't find <svg> tag in `dot` output");
  return Result.substr(Pos).str();
}

} // namespace

std::unique_ptr<Logger>
Logger::html(std::function<std::unique_ptr<llvm::raw_ostream>()> Streams) {
  return std::make_unique<HTMLLogger>(std::move(Streams));
}

} // namespace clang::dataflow
