Path: blob/main/contrib/llvm-project/clang/lib/ARCMigrate/PlistReporter.cpp
35236 views
//===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#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"13using namespace clang;14using namespace arcmt;15using namespace markup;1617static StringRef getLevelName(DiagnosticsEngine::Level Level) {18switch (Level) {19case DiagnosticsEngine::Ignored:20llvm_unreachable("ignored");21case DiagnosticsEngine::Note:22return "note";23case DiagnosticsEngine::Remark:24case DiagnosticsEngine::Warning:25return "warning";26case DiagnosticsEngine::Fatal:27case DiagnosticsEngine::Error:28return "error";29}30llvm_unreachable("Invalid DiagnosticsEngine level!");31}3233void arcmt::writeARCDiagsToPlist(const std::string &outPath,34ArrayRef<StoredDiagnostic> diags,35SourceManager &SM,36const LangOptions &LangOpts) {37DiagnosticIDs DiagIDs;3839// Build up a set of FIDs that we use by scanning the locations and40// ranges of the diagnostics.41FIDMap FM;42SmallVector<FileID, 10> Fids;4344for (ArrayRef<StoredDiagnostic>::iterator45I = diags.begin(), E = diags.end(); I != E; ++I) {46const StoredDiagnostic &D = *I;4748AddFID(FM, Fids, SM, D.getLocation());4950for (StoredDiagnostic::range_iterator51RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) {52AddFID(FM, Fids, SM, RI->getBegin());53AddFID(FM, Fids, SM, RI->getEnd());54}55}5657std::error_code EC;58llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::OF_TextWithCRLF);59if (EC) {60llvm::errs() << "error: could not create file: " << outPath << '\n';61return;62}6364EmitPlistHeader(o);6566// Write the root object: a <dict> containing...67// - "files", an <array> mapping from FIDs to file names68// - "diagnostics", an <array> containing the diagnostics69o << "<dict>\n"70" <key>files</key>\n"71" <array>\n";7273for (FileID FID : Fids)74EmitString(o << " ", SM.getFileEntryRefForID(FID)->getName()) << '\n';7576o << " </array>\n"77" <key>diagnostics</key>\n"78" <array>\n";7980for (ArrayRef<StoredDiagnostic>::iterator81DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {8283const StoredDiagnostic &D = *DI;8485if (D.getLevel() == DiagnosticsEngine::Ignored)86continue;8788o << " <dict>\n";8990// Output the diagnostic.91o << " <key>description</key>";92EmitString(o, D.getMessage()) << '\n';93o << " <key>category</key>";94EmitString(o, DiagIDs.getCategoryNameFromID(95DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n';96o << " <key>type</key>";97EmitString(o, getLevelName(D.getLevel())) << '\n';9899// Output the location of the bug.100o << " <key>location</key>\n";101EmitLocation(o, SM, D.getLocation(), FM, 2);102103// Output the ranges (if any).104if (!D.getRanges().empty()) {105o << " <key>ranges</key>\n";106o << " <array>\n";107for (auto &R : D.getRanges()) {108CharSourceRange ExpansionRange = SM.getExpansionRange(R);109EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),110FM, 4);111}112o << " </array>\n";113}114115// Close up the entry.116o << " </dict>\n";117}118119o << " </array>\n";120121// Finish.122o << "</dict>\n</plist>\n";123}124125126