17ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis//===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===// 27ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// 37ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// The LLVM Compiler Infrastructure 47ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// 57ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 67ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// License. See LICENSE.TXT for details. 77ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// 87ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 97ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 107ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis#include "Internals.h" 117ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis#include "clang/Lex/Lexer.h" 127ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h" 137ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis#include "clang/Basic/FileManager.h" 147ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidisusing namespace clang; 157ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidisusing namespace arcmt; 167ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 177ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// FIXME: This duplicates significant functionality from PlistDiagnostics.cpp, 187ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis// it would be jolly good if there was a reusable PlistWriter or something. 197ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 207ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidistypedef llvm::DenseMap<FileID, unsigned> FIDMap; 217ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, 237ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const SourceManager &SM, SourceLocation L) { 247ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 25402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 267ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis FIDMap::iterator I = FIDs.find(FID); 277ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis if (I != FIDs.end()) return; 287ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis FIDs[FID] = V.size(); 297ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis V.push_back(FID); 307ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 317ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 327ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidisstatic unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM, 337ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis SourceLocation L) { 34402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth FileID FID = SM.getFileID(SM.getExpansionLoc(L)); 357ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis FIDMap::const_iterator I = FIDs.find(FID); 367ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis assert(I != FIDs.end()); 377ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis return I->second; 387ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 397ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 405f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic raw_ostream& Indent(raw_ostream& o, const unsigned indent) { 417ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis for (unsigned i = 0; i < indent; ++i) o << ' '; 427ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis return o; 437ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 447ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void EmitLocation(raw_ostream& o, const SourceManager &SM, 467ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const LangOptions &LangOpts, 477ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis SourceLocation L, const FIDMap &FM, 487ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis unsigned indent, bool extend = false) { 497ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 50402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager&>(SM)); 517ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 527ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Add in the length of the token, so that we cover multi-char tokens. 537ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis unsigned offset = 547ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0; 557ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 567ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << "<dict>\n"; 577ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << " <key>line</key><integer>" 58642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << Loc.getExpansionLineNumber() << "</integer>\n"; 597ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << " <key>col</key><integer>" 60a77c031cb66f75d22672070052cc6e0205289ff8Chandler Carruth << Loc.getExpansionColumnNumber() + offset << "</integer>\n"; 617ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << " <key>file</key><integer>" 627ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis << GetFID(FM, SM, Loc) << "</integer>\n"; 637ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << "</dict>\n"; 647ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 657ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void EmitRange(raw_ostream& o, const SourceManager &SM, 677ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const LangOptions &LangOpts, 687ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis CharSourceRange R, const FIDMap &FM, 697ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis unsigned indent) { 707ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << "<array>\n"; 717ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1); 727ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, R.isTokenRange()); 737ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis Indent(o, indent) << "</array>\n"; 747ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 757ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic raw_ostream& EmitString(raw_ostream& o, 777ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis StringRef s) { 787ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << "<string>"; 797ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis for (StringRef::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) { 807ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis char c = *I; 817ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis switch (c) { 827ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis default: o << c; break; 837ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis case '&': o << "&"; break; 847ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis case '<': o << "<"; break; 857ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis case '>': o << ">"; break; 867ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis case '\'': o << "'"; break; 877ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis case '\"': o << """; break; 887ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 897ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 907ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << "</string>"; 917ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis return o; 927ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 937ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 947ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidisvoid arcmt::writeARCDiagsToPlist(const std::string &outPath, 952d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner ArrayRef<StoredDiagnostic> diags, 967ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis SourceManager &SM, 977ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const LangOptions &LangOpts) { 987ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis DiagnosticIDs DiagIDs; 997ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1007ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Build up a set of FIDs that we use by scanning the locations and 1017ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // ranges of the diagnostics. 1027ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis FIDMap FM; 1035f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<FileID, 10> Fids; 1047ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1052d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner for (ArrayRef<StoredDiagnostic>::iterator 1067ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis I = diags.begin(), E = diags.end(); I != E; ++I) { 1077ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const StoredDiagnostic &D = *I; 1087ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1097ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis AddFID(FM, Fids, SM, D.getLocation()); 1107ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1117ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis for (StoredDiagnostic::range_iterator 1127ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) { 1137ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis AddFID(FM, Fids, SM, RI->getBegin()); 1147ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis AddFID(FM, Fids, SM, RI->getEnd()); 1157ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1167ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1177ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1187ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis std::string errMsg; 1197ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis llvm::raw_fd_ostream o(outPath.c_str(), errMsg); 1207ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis if (!errMsg.empty()) { 1217ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis llvm::errs() << "error: could not create file: " << outPath << '\n'; 1227ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis return; 1237ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1247ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1257ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Write the plist header. 1267ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 1277ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " 1287ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" 1297ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis "<plist version=\"1.0\">\n"; 1307ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1317ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Write the root object: a <dict> containing... 1327ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // - "files", an <array> mapping from FIDs to file names 1337ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // - "diagnostics", an <array> containing the diagnostics 1347ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << "<dict>\n" 1357ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis " <key>files</key>\n" 1367ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis " <array>\n"; 1377ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end(); 1397ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis I!=E; ++I) { 1407ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " "; 1417ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, SM.getFileEntryForID(*I)->getName()) << '\n'; 1427ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1437ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1447ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " </array>\n" 1457ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis " <key>diagnostics</key>\n" 1467ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis " <array>\n"; 1477ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1482d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner for (ArrayRef<StoredDiagnostic>::iterator 1497ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) { 1507ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1517ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis const StoredDiagnostic &D = *DI; 1527ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 153d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie if (D.getLevel() == DiagnosticsEngine::Ignored) 1547ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis continue; 1557ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1567ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <dict>\n"; 1577ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1587ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Output the diagnostic. 1597ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <key>description</key>"; 1607ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, D.getMessage()) << '\n'; 1617ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <key>category</key>"; 1627ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, DiagIDs.getCategoryNameFromID( 1637ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n'; 1647ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <key>type</key>"; 165d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie if (D.getLevel() >= DiagnosticsEngine::Error) 1667ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, "error") << '\n'; 167d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie else if (D.getLevel() == DiagnosticsEngine::Warning) 1687ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, "warning") << '\n'; 1697ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis else 1707ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitString(o, "note") << '\n'; 1717ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1727ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Output the location of the bug. 1737ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <key>location</key>\n"; 1747ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2); 1757ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1767ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Output the ranges (if any). 1777ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end(); 1787ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1797ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis if (RI != RE) { 1807ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <key>ranges</key>\n"; 1817ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " <array>\n"; 1827ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis for (; RI != RE; ++RI) 1837ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis EmitRange(o, SM, LangOpts, *RI, FM, 4); 1847ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " </array>\n"; 1857ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1867ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1877ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Close up the entry. 1887ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " </dict>\n"; 1897ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis } 1907ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1917ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << " </array>\n"; 1927ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis 1937ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis // Finish. 1947ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis o << "</dict>\n</plist>"; 1957ee2049278b98d42709380054eb83f4952af1200Argyrios Kyrtzidis} 196