PlistReporter.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. //===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "Internals.h"
  10. #include "clang/Basic/FileManager.h"
  11. #include "clang/Basic/PlistSupport.h"
  12. #include "clang/Basic/SourceManager.h"
  13. #include "clang/Lex/Lexer.h"
  14. using namespace clang;
  15. using namespace arcmt;
  16. using namespace markup;
  17. static StringRef getLevelName(DiagnosticsEngine::Level Level) {
  18. switch (Level) {
  19. case DiagnosticsEngine::Ignored:
  20. llvm_unreachable("ignored");
  21. case DiagnosticsEngine::Note:
  22. return "note";
  23. case DiagnosticsEngine::Remark:
  24. case DiagnosticsEngine::Warning:
  25. return "warning";
  26. case DiagnosticsEngine::Fatal:
  27. case DiagnosticsEngine::Error:
  28. return "error";
  29. }
  30. llvm_unreachable("Invalid DiagnosticsEngine level!");
  31. }
  32. void arcmt::writeARCDiagsToPlist(const std::string &outPath,
  33. ArrayRef<StoredDiagnostic> diags,
  34. SourceManager &SM,
  35. const LangOptions &LangOpts) {
  36. DiagnosticIDs DiagIDs;
  37. // Build up a set of FIDs that we use by scanning the locations and
  38. // ranges of the diagnostics.
  39. FIDMap FM;
  40. SmallVector<FileID, 10> Fids;
  41. for (ArrayRef<StoredDiagnostic>::iterator
  42. I = diags.begin(), E = diags.end(); I != E; ++I) {
  43. const StoredDiagnostic &D = *I;
  44. AddFID(FM, Fids, SM, D.getLocation());
  45. for (StoredDiagnostic::range_iterator
  46. RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) {
  47. AddFID(FM, Fids, SM, RI->getBegin());
  48. AddFID(FM, Fids, SM, RI->getEnd());
  49. }
  50. }
  51. std::error_code EC;
  52. llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::F_Text);
  53. if (EC) {
  54. llvm::errs() << "error: could not create file: " << outPath << '\n';
  55. return;
  56. }
  57. EmitPlistHeader(o);
  58. // Write the root object: a <dict> containing...
  59. // - "files", an <array> mapping from FIDs to file names
  60. // - "diagnostics", an <array> containing the diagnostics
  61. o << "<dict>\n"
  62. " <key>files</key>\n"
  63. " <array>\n";
  64. for (FileID FID : Fids)
  65. EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n';
  66. o << " </array>\n"
  67. " <key>diagnostics</key>\n"
  68. " <array>\n";
  69. for (ArrayRef<StoredDiagnostic>::iterator
  70. DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {
  71. const StoredDiagnostic &D = *DI;
  72. if (D.getLevel() == DiagnosticsEngine::Ignored)
  73. continue;
  74. o << " <dict>\n";
  75. // Output the diagnostic.
  76. o << " <key>description</key>";
  77. EmitString(o, D.getMessage()) << '\n';
  78. o << " <key>category</key>";
  79. EmitString(o, DiagIDs.getCategoryNameFromID(
  80. DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n';
  81. o << " <key>type</key>";
  82. EmitString(o, getLevelName(D.getLevel())) << '\n';
  83. // Output the location of the bug.
  84. o << " <key>location</key>\n";
  85. EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2);
  86. // Output the ranges (if any).
  87. StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end();
  88. if (RI != RE) {
  89. o << " <key>ranges</key>\n";
  90. o << " <array>\n";
  91. for (; RI != RE; ++RI)
  92. EmitRange(o, SM, LangOpts, *RI, FM, 4);
  93. o << " </array>\n";
  94. }
  95. // Close up the entry.
  96. o << " </dict>\n";
  97. }
  98. o << " </array>\n";
  99. // Finish.
  100. o << "</dict>\n</plist>";
  101. }