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