//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the HTMLDiagnostics object.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include <fstream>
using namespace clang;

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

namespace {

class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
  llvm::sys::Path Directory, FilePrefix;
  bool createdDir, noDir;
  Preprocessor* PP;
  std::vector<const PathDiagnostic*> BatchedDiags;  
public:
  HTMLDiagnostics(const std::string& prefix, Preprocessor* pp);

  virtual ~HTMLDiagnostics();
  
  virtual void SetPreprocessor(Preprocessor *pp) { PP = pp; }
  
  virtual void HandlePathDiagnostic(const PathDiagnostic* D);
  
  unsigned ProcessMacroPiece(llvm::raw_ostream& os,
                             const PathDiagnosticMacroPiece& P,
                             unsigned num);
    
  void HandlePiece(Rewriter& R, FileID BugFileID,
                   const PathDiagnosticPiece& P, 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);
};
  
} // end anonymous namespace

HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp)
  : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
    PP(pp) {
  
  // All html files begin with "report" 
  FilePrefix.appendComponent("report");
}

PathDiagnosticClient*
clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
                                  PreprocessorFactory*) {
  return new HTMLDiagnostics(prefix, PP);
}

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

void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
  if (!D)
    return;
  
  if (D->empty()) {
    delete D;
    return;
  }
  
  const_cast<PathDiagnostic*>(D)->flattenLocations();
  BatchedDiags.push_back(D);
}

HTMLDiagnostics::~HTMLDiagnostics() {
  while (!BatchedDiags.empty()) {
    const PathDiagnostic* D = BatchedDiags.back();
    BatchedDiags.pop_back();
    ReportDiag(*D);
    delete D;
  }  
}

void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
  // Create the HTML directory if it is missing.
  if (!createdDir) {
    createdDir = true;
    std::string ErrorMsg;
    Directory.createDirectoryOnDisk(true, &ErrorMsg);
  
    if (!Directory.isDirectory()) {
      llvm::cerr << "warning: could not create directory '"
                 << Directory.toString() << "'\n"
                 << "reason: " << ErrorMsg << '\n'; 
      
      noDir = true;
      
      return;
    }
  }
  
  if (noDir)
    return;
  
  const SourceManager &SMgr = D.begin()->getLocation().getManager();
  FileID FID;
  
  // Verify that the entire path is from the same FileID.
  for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) {
    FullSourceLoc L = I->getLocation().asLocation().getInstantiationLoc();
    
    if (FID.isInvalid()) {
      FID = SMgr.getFileID(L);
    } else if (SMgr.getFileID(L) != FID)
      return; // FIXME: Emit a warning?
    
    // Check the source ranges.
    for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
                                             RE=I->ranges_end(); RI!=RE; ++RI) {
      
      SourceLocation L = SMgr.getInstantiationLoc(RI->getBegin());

      if (!L.isFileID() || SMgr.getFileID(L) != FID)
        return; // FIXME: Emit a warning?
      
      L = SMgr.getInstantiationLoc(RI->getEnd());
      
      if (!L.isFileID() || SMgr.getFileID(L) != FID)
        return; // FIXME: Emit a warning?      
    }
  }
  
  if (FID.isInvalid())
    return; // FIXME: Emit a warning?
  
  // Create a new rewriter to generate HTML.
  Rewriter R(const_cast<SourceManager&>(SMgr), PP->getLangOptions());
  
  // Process the path.  
  unsigned n = D.size();
  unsigned max = n;
  
  for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
        I!=E; ++I, --n)
    HandlePiece(R, FID, *I, n, max);
  
  // Add line numbers, header, footer, etc.
  
  // unsigned FID = R.getSourceMgr().getMainFileID();
  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.
  
  if (PP) html::SyntaxHighlight(R, FID, *PP);

  // FIXME: We eventually want to use PPF to create a fresh Preprocessor,
  //  once we have worked out the bugs.
  //
  // if (PPF) html::HighlightMacros(R, FID, *PPF);
  //
  if (PP) html::HighlightMacros(R, FID, *PP);
  
  // Get the full directory name of the analyzed file.

  const FileEntry* Entry = SMgr.getFileEntryForID(FID);
  
  // 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.

  std::string DirName = "";
  
  if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
    llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
    DirName = P.toString() + "/";
  }
    
  // 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\">Location:</td><td>"
         "<a href=\"#EndPath\">line "      
      << (*D.rbegin()).getLocation().asLocation().getInstantiationLineNumber()
      << ", column "
      << (*D.rbegin()).getLocation().asLocation().getInstantiationColumnNumber()
      << "</a></td></tr>\n"
         "<tr><td class=\"rowname\">Description:</td><td>"
      << D.getDescription() << "</td></tr>\n";
    
    // 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 << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
          "<h3>Annotated Source Code</h3>\n";    
    
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  // Embed meta-data tags.
  
  const std::string& BugDesc = D.getDescription();
  
  if (!BugDesc.empty()) {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  const std::string& BugType = D.getBugType();
  if (!BugType.empty()) {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGTYPE " << BugType << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  const std::string& BugCategory = D.getCategory();
  
  if (!BugCategory.empty()) {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGLINE "
       << D.back()->getLocation().asLocation().getInstantiationLineNumber()
       << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }
  
  {
    std::string s;
    llvm::raw_string_ostream os(s);
    os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
    R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
  }

  // Add CSS, header, and footer.
  
  html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
  
  // Get the rewrite buffer.
  const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
  
  if (!Buf) {
    llvm::cerr << "warning: no diagnostics generated for main file.\n";
    return;
  }

  // Create the stream to write out the HTML.
  std::ofstream os;
  
  {
    // Create a path for the target HTML file.
    llvm::sys::Path F(FilePrefix);
    F.makeUnique(false, NULL);
  
    // Rename the file with an HTML extension.
    llvm::sys::Path H(F);
    H.appendSuffix("html");
    F.renamePathOnDisk(H, NULL);
    
    os.open(H.toString().c_str());
    
    if (!os) {
      llvm::cerr << "warning: could not create file '" << F.toString() << "'\n";
      return;
    }
  }
  
  // Emit the HTML to disk.

  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
      os << *I;
}

void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
                                  const PathDiagnosticPiece& P,
                                  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.getDecomposedInstantiationLoc(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.getInstantiationLoc().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 = 0;
  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;
  }
    
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);
    
  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
    
  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 std::string& Msg = P.getString();
    unsigned max_token = 0;
    unsigned cnt = 0;
    unsigned len = Msg.size();
    
    for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
      switch (*I) {
        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 (max > 1) {
    os << "<table class=\"msgT\"><tr><td valign=\"top\">";
    os << "<div class=\"PathIndex";
    if (Kind) os << " PathIndex" << Kind;
    os << "\">" << num << "</div>";
    os << "</td><td>";
  }

  if (const PathDiagnosticMacroPiece *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().getInstantiationLoc();
      assert(L.isFileID());
      std::pair<const char*, const char*> BufferInfo = L.getBufferData();
      const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
      Lexer rawLexer(L, PP->getLangOptions(), BufferInfo.first,
                     MacroName, BufferInfo.second);
      
      Token TheTok;
      rawLexer.LexFromRawLexer(TheTok);
      for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
        os << MacroName[i];
    }
      
    os << "':\n";
    
    if (max > 1)
      os << "</td></tr></table>";

    // Within a macro piece.  Write out each event.
    ProcessMacroPiece(os, *MP, 0);
  }
  else {
    os << html::EscapeText(P.getString());
    
    if (max > 1)
      os << "</td></tr></table>";
  }
  
  os << "</div></td></tr>";

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

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

  // Now highlight the ranges.  
  for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
        I != E; ++I)
    HighlightRange(R, LPosInfo.first, *I);

#if 0
  // If there is a code insertion hint, insert that code.
  // FIXME: This code is disabled because it seems to mangle the HTML
  // output. I'm leaving it here because it's generally the right idea,
  // but needs some help from someone more familiar with the rewriter.
  for (const CodeModificationHint *Hint = P.code_modifications_begin(),
                               *HintEnd = P.code_modifications_end();
       Hint != HintEnd; ++Hint) {
    if (Hint->RemoveRange.isValid()) {
      HighlightRange(R, LPosInfo.first, Hint->RemoveRange,
                     "<span class=\"CodeRemovalHint\">", "</span>");
    }
    if (Hint->InsertionLoc.isValid()) {
      std::string EscapedCode = html::EscapeText(Hint->CodeToInsert, true);
      EscapedCode = "<span class=\"CodeInsertionHint\">" + EscapedCode
        + "</span>";
      R.InsertStrBefore(Hint->InsertionLoc, EscapedCode);
    }
  }
#endif
}

static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) {
  llvm::SmallVector<char, 10> buf;

  do {
    unsigned x = n % ('z' - 'a');
    buf.push_back('a' + x);
    n = n / ('z' - 'a');
  } while (n);
  
  assert(!buf.empty());
  
  for (llvm::SmallVectorImpl<char>::reverse_iterator I=buf.rbegin(),
       E=buf.rend(); I!=E; ++I)
    os << *I;
}

unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os,
                                            const PathDiagnosticMacroPiece& P,
                                            unsigned num) {
  
  for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
        I!=E; ++I) {
    
    if (const PathDiagnosticMacroPiece *MP =
          dyn_cast<PathDiagnosticMacroPiece>(*I)) {
      num = ProcessMacroPiece(os, *MP, num);
      continue;
    }

    if (PathDiagnosticEventPiece *EP = dyn_cast<PathDiagnosticEventPiece>(*I)) {
      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.getInstantiationLoc(Range.getBegin());
  unsigned StartLineNo = SM.getInstantiationLineNumber(InstantiationStart);
  
  SourceLocation InstantiationEnd = SM.getInstantiationLoc(Range.getEnd());
  unsigned EndLineNo = SM.getInstantiationLineNumber(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.getInstantiationColumnNumber(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.getFileLocWithOffset(EndColNo - OldEndColNo);
  
  html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
}
