//===--- PlistDiagnostics.cpp - Plist 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 PlistDiagnostics object.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
using namespace ento;
using llvm::cast;

typedef llvm::DenseMap<FileID, unsigned> FIDMap;

namespace clang {
  class Preprocessor;
}

namespace {
struct CompareDiagnostics {
  // Compare if 'X' is "<" than 'Y'.
  bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
    // First compare by location
    const FullSourceLoc &XLoc = X->getLocation().asLocation();
    const FullSourceLoc &YLoc = Y->getLocation().asLocation();
    if (XLoc < YLoc)
      return true;
    if (XLoc != YLoc)
      return false;
    
    // Next, compare by bug type.
    llvm::StringRef XBugType = X->getBugType();
    llvm::StringRef YBugType = Y->getBugType();
    if (XBugType < YBugType)
      return true;
    if (XBugType != YBugType)
      return false;
    
    // Next, compare by bug description.
    llvm::StringRef XDesc = X->getDescription();
    llvm::StringRef YDesc = Y->getDescription();
    if (XDesc < YDesc)
      return true;
    if (XDesc != YDesc)
      return false;
    
    // FIXME: Further refine by comparing PathDiagnosticPieces?
    return false;    
  }  
};  
}

namespace {
  class PlistDiagnostics : public PathDiagnosticClient {
    std::vector<const PathDiagnostic*> BatchedDiags;
    const std::string OutputFile;
    const LangOptions &LangOpts;
    llvm::OwningPtr<PathDiagnosticClient> SubPD;
    bool flushed;
  public:
    PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
                     PathDiagnosticClient *subPD);

    ~PlistDiagnostics() { FlushDiagnostics(NULL); }

    void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
    
    void HandlePathDiagnostic(const PathDiagnostic* D);
    
    virtual llvm::StringRef getName() const {
      return "PlistDiagnostics";
    }

    PathGenerationScheme getGenerationScheme() const;
    bool supportsLogicalOpControlFlow() const { return true; }
    bool supportsAllBlockEdges() const { return true; }
    virtual bool useVerboseDescription() const { return false; }
  };
} // end anonymous namespace

PlistDiagnostics::PlistDiagnostics(const std::string& output,
                                   const LangOptions &LO,
                                   PathDiagnosticClient *subPD)
  : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}

PathDiagnosticClient*
ento::createPlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
                                  PathDiagnosticClient *subPD) {
  return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
}

PathDiagnosticClient::PathGenerationScheme
PlistDiagnostics::getGenerationScheme() const {
  if (const PathDiagnosticClient *PD = SubPD.get())
    return PD->getGenerationScheme();

  return Extensive;
}

static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
                   const SourceManager* SM, SourceLocation L) {

  FileID FID = SM->getFileID(SM->getInstantiationLoc(L));
  FIDMap::iterator I = FIDs.find(FID);
  if (I != FIDs.end()) return;
  FIDs[FID] = V.size();
  V.push_back(FID);
}

static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
                       SourceLocation L) {
  FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
  FIDMap::const_iterator I = FIDs.find(FID);
  assert(I != FIDs.end());
  return I->second;
}

static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
  for (unsigned i = 0; i < indent; ++i) o << ' ';
  return o;
}

static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
                         const LangOptions &LangOpts,
                         SourceLocation L, const FIDMap &FM,
                         unsigned indent, bool extend = false) {

  FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));

  // Add in the length of the token, so that we cover multi-char tokens.
  unsigned offset =
    extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;

  Indent(o, indent) << "<dict>\n";
  Indent(o, indent) << " <key>line</key><integer>"
                    << Loc.getInstantiationLineNumber() << "</integer>\n";
  Indent(o, indent) << " <key>col</key><integer>"
                    << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
  Indent(o, indent) << " <key>file</key><integer>"
                    << GetFID(FM, SM, Loc) << "</integer>\n";
  Indent(o, indent) << "</dict>\n";
}

static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
                         const LangOptions &LangOpts,
                         const PathDiagnosticLocation &L, const FIDMap& FM,
                         unsigned indent, bool extend = false) {
  EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
}

static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
                      const LangOptions &LangOpts,
                      PathDiagnosticRange R, const FIDMap &FM,
                      unsigned indent) {
  Indent(o, indent) << "<array>\n";
  EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
  EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
  Indent(o, indent) << "</array>\n";
}

static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
                                     const std::string& s) {
  o << "<string>";
  for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
    char c = *I;
    switch (c) {
    default:   o << c; break;
    case '&':  o << "&amp;"; break;
    case '<':  o << "&lt;"; break;
    case '>':  o << "&gt;"; break;
    case '\'': o << "&apos;"; break;
    case '\"': o << "&quot;"; break;
    }
  }
  o << "</string>";
  return o;
}

static void ReportControlFlow(llvm::raw_ostream& o,
                              const PathDiagnosticControlFlowPiece& P,
                              const FIDMap& FM,
                              const SourceManager &SM,
                              const LangOptions &LangOpts,
                              unsigned indent) {

  Indent(o, indent) << "<dict>\n";
  ++indent;

  Indent(o, indent) << "<key>kind</key><string>control</string>\n";

  // Emit edges.
  Indent(o, indent) << "<key>edges</key>\n";
  ++indent;
  Indent(o, indent) << "<array>\n";
  ++indent;
  for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
       I!=E; ++I) {
    Indent(o, indent) << "<dict>\n";
    ++indent;
    Indent(o, indent) << "<key>start</key>\n";
    EmitRange(o, SM, LangOpts, I->getStart().asRange(), FM, indent+1);
    Indent(o, indent) << "<key>end</key>\n";
    EmitRange(o, SM, LangOpts, I->getEnd().asRange(), FM, indent+1);
    --indent;
    Indent(o, indent) << "</dict>\n";
  }
  --indent;
  Indent(o, indent) << "</array>\n";
  --indent;

  // Output any helper text.
  const std::string& s = P.getString();
  if (!s.empty()) {
    Indent(o, indent) << "<key>alternate</key>";
    EmitString(o, s) << '\n';
  }

  --indent;
  Indent(o, indent) << "</dict>\n";
}

static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
                        const FIDMap& FM,
                        const SourceManager &SM,
                        const LangOptions &LangOpts,
                        unsigned indent) {

  Indent(o, indent) << "<dict>\n";
  ++indent;

  Indent(o, indent) << "<key>kind</key><string>event</string>\n";

  // Output the location.
  FullSourceLoc L = P.getLocation().asLocation();

  Indent(o, indent) << "<key>location</key>\n";
  EmitLocation(o, SM, LangOpts, L, FM, indent);

  // Output the ranges (if any).
  PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
  RE = P.ranges_end();

  if (RI != RE) {
    Indent(o, indent) << "<key>ranges</key>\n";
    Indent(o, indent) << "<array>\n";
    ++indent;
    for (; RI != RE; ++RI)
      EmitRange(o, SM, LangOpts, *RI, FM, indent+1);
    --indent;
    Indent(o, indent) << "</array>\n";
  }

  // Output the text.
  assert(!P.getString().empty());
  Indent(o, indent) << "<key>extended_message</key>\n";
  Indent(o, indent);
  EmitString(o, P.getString()) << '\n';

  // Output the short text.
  // FIXME: Really use a short string.
  Indent(o, indent) << "<key>message</key>\n";
  EmitString(o, P.getString()) << '\n';

  // Finish up.
  --indent;
  Indent(o, indent); o << "</dict>\n";
}

static void ReportMacro(llvm::raw_ostream& o,
                        const PathDiagnosticMacroPiece& P,
                        const FIDMap& FM, const SourceManager &SM,
                        const LangOptions &LangOpts,
                        unsigned indent) {

  for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
       I!=E; ++I) {

    switch ((*I)->getKind()) {
    default:
      break;
    case PathDiagnosticPiece::Event:
      ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
                  indent);
      break;
    case PathDiagnosticPiece::Macro:
      ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
                  indent);
      break;
    }
  }
}

static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
                       const FIDMap& FM, const SourceManager &SM,
                       const LangOptions &LangOpts) {

  unsigned indent = 4;

  switch (P.getKind()) {
  case PathDiagnosticPiece::ControlFlow:
    ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
                      LangOpts, indent);
    break;
  case PathDiagnosticPiece::Event:
    ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
                indent);
    break;
  case PathDiagnosticPiece::Macro:
    ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
                indent);
    break;
  }
}

void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
  if (!D)
    return;

  if (D->empty()) {
    delete D;
    return;
  }

  // We need to flatten the locations (convert Stmt* to locations) because
  // the referenced statements may be freed by the time the diagnostics
  // are emitted.
  const_cast<PathDiagnostic*>(D)->flattenLocations();
  BatchedDiags.push_back(D);
}

void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
                                        *FilesMade) {
  
  if (flushed)
    return;
  
  flushed = true;
  
  // Sort the diagnostics so that they are always emitted in a deterministic
  // order.
  if (!BatchedDiags.empty())
    std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics()); 

  // Build up a set of FIDs that we use by scanning the locations and
  // ranges of the diagnostics.
  FIDMap FM;
  llvm::SmallVector<FileID, 10> Fids;
  const SourceManager* SM = 0;

  if (!BatchedDiags.empty())
    SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager();

  for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(),
       DE = BatchedDiags.end(); DI != DE; ++DI) {

    const PathDiagnostic *D = *DI;

    for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) {
      AddFID(FM, Fids, SM, I->getLocation().asLocation());

      for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
           RE=I->ranges_end(); RI!=RE; ++RI) {
        AddFID(FM, Fids, SM, RI->getBegin());
        AddFID(FM, Fids, SM, RI->getEnd());
      }
    }
  }

  // Open the file.
  std::string ErrMsg;
  llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
  if (!ErrMsg.empty()) {
    llvm::errs() << "warning: could not creat file: " << OutputFile << '\n';
    return;
  }

  // Write the plist header.
  o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
  "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
  "<plist version=\"1.0\">\n";

  // Write the root object: a <dict> containing...
  //  - "files", an <array> mapping from FIDs to file names
  //  - "diagnostics", an <array> containing the path diagnostics
  o << "<dict>\n"
       " <key>files</key>\n"
       " <array>\n";

  for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
       I!=E; ++I) {
    o << "  ";
    EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
  }

  o << " </array>\n"
       " <key>diagnostics</key>\n"
       " <array>\n";

  for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(),
       DE = BatchedDiags.end(); DI!=DE; ++DI) {

    o << "  <dict>\n"
         "   <key>path</key>\n";

    const PathDiagnostic *D = *DI;
    // Create an owning smart pointer for 'D' just so that we auto-free it
    // when we exit this method.
    llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));

    o << "   <array>\n";

    for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
      ReportDiag(o, *I, FM, *SM, LangOpts);

    o << "   </array>\n";

    // Output the bug type and bug category.
    o << "   <key>description</key>";
    EmitString(o, D->getDescription()) << '\n';
    o << "   <key>category</key>";
    EmitString(o, D->getCategory()) << '\n';
    o << "   <key>type</key>";
    EmitString(o, D->getBugType()) << '\n';

    // Output the location of the bug.
    o << "  <key>location</key>\n";
    EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);

    // Output the diagnostic to the sub-diagnostic client, if any.
    if (SubPD) {
      SubPD->HandlePathDiagnostic(OwnedD.take());
      llvm::SmallVector<std::string, 1> SubFilesMade;
      SubPD->FlushDiagnostics(SubFilesMade);

      if (!SubFilesMade.empty()) {
        o << "  <key>" << SubPD->getName() << "_files</key>\n";
        o << "  <array>\n";
        for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
          o << "   <string>" << SubFilesMade[i] << "</string>\n";
        o << "  </array>\n";
      }
    }

    // Close up the entry.
    o << "  </dict>\n";
  }

  o << " </array>\n";

  // Finish.
  o << "</dict>\n</plist>";
  
  if (FilesMade)
    FilesMade->push_back(OutputFile);
  
  BatchedDiags.clear();
}
