clang API Documentation
00001 //===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "Internals.h" 00011 #include "clang/Basic/FileManager.h" 00012 #include "clang/Basic/PlistSupport.h" 00013 #include "clang/Basic/SourceManager.h" 00014 #include "clang/Lex/Lexer.h" 00015 using namespace clang; 00016 using namespace arcmt; 00017 using namespace markup; 00018 00019 static StringRef getLevelName(DiagnosticsEngine::Level Level) { 00020 switch (Level) { 00021 case DiagnosticsEngine::Ignored: 00022 llvm_unreachable("ignored"); 00023 case DiagnosticsEngine::Note: 00024 return "note"; 00025 case DiagnosticsEngine::Remark: 00026 case DiagnosticsEngine::Warning: 00027 return "warning"; 00028 case DiagnosticsEngine::Fatal: 00029 case DiagnosticsEngine::Error: 00030 return "error"; 00031 } 00032 llvm_unreachable("Invalid DiagnosticsEngine level!"); 00033 } 00034 00035 void arcmt::writeARCDiagsToPlist(const std::string &outPath, 00036 ArrayRef<StoredDiagnostic> diags, 00037 SourceManager &SM, 00038 const LangOptions &LangOpts) { 00039 DiagnosticIDs DiagIDs; 00040 00041 // Build up a set of FIDs that we use by scanning the locations and 00042 // ranges of the diagnostics. 00043 FIDMap FM; 00044 SmallVector<FileID, 10> Fids; 00045 00046 for (ArrayRef<StoredDiagnostic>::iterator 00047 I = diags.begin(), E = diags.end(); I != E; ++I) { 00048 const StoredDiagnostic &D = *I; 00049 00050 AddFID(FM, Fids, SM, D.getLocation()); 00051 00052 for (StoredDiagnostic::range_iterator 00053 RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) { 00054 AddFID(FM, Fids, SM, RI->getBegin()); 00055 AddFID(FM, Fids, SM, RI->getEnd()); 00056 } 00057 } 00058 00059 std::error_code EC; 00060 llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::F_Text); 00061 if (EC) { 00062 llvm::errs() << "error: could not create file: " << outPath << '\n'; 00063 return; 00064 } 00065 00066 EmitPlistHeader(o); 00067 00068 // Write the root object: a <dict> containing... 00069 // - "files", an <array> mapping from FIDs to file names 00070 // - "diagnostics", an <array> containing the diagnostics 00071 o << "<dict>\n" 00072 " <key>files</key>\n" 00073 " <array>\n"; 00074 00075 for (FileID FID : Fids) 00076 EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n'; 00077 00078 o << " </array>\n" 00079 " <key>diagnostics</key>\n" 00080 " <array>\n"; 00081 00082 for (ArrayRef<StoredDiagnostic>::iterator 00083 DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) { 00084 00085 const StoredDiagnostic &D = *DI; 00086 00087 if (D.getLevel() == DiagnosticsEngine::Ignored) 00088 continue; 00089 00090 o << " <dict>\n"; 00091 00092 // Output the diagnostic. 00093 o << " <key>description</key>"; 00094 EmitString(o, D.getMessage()) << '\n'; 00095 o << " <key>category</key>"; 00096 EmitString(o, DiagIDs.getCategoryNameFromID( 00097 DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n'; 00098 o << " <key>type</key>"; 00099 EmitString(o, getLevelName(D.getLevel())) << '\n'; 00100 00101 // Output the location of the bug. 00102 o << " <key>location</key>\n"; 00103 EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2); 00104 00105 // Output the ranges (if any). 00106 StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end(); 00107 00108 if (RI != RE) { 00109 o << " <key>ranges</key>\n"; 00110 o << " <array>\n"; 00111 for (; RI != RE; ++RI) 00112 EmitRange(o, SM, LangOpts, *RI, FM, 4); 00113 o << " </array>\n"; 00114 } 00115 00116 // Close up the entry. 00117 o << " </dict>\n"; 00118 } 00119 00120 o << " </array>\n"; 00121 00122 // Finish. 00123 o << "</dict>\n</plist>"; 00124 }