PlistReporter.cpp 3.6 KB

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