File indexing completed on 2026-05-10 08:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H
0010 #define LLVM_CLANG_BASIC_PLISTSUPPORT_H
0011
0012 #include "clang/Basic/LLVM.h"
0013 #include "clang/Basic/SourceLocation.h"
0014 #include "clang/Basic/SourceManager.h"
0015 #include "llvm/ADT/DenseMap.h"
0016 #include "llvm/ADT/SmallVector.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/Support/raw_ostream.h"
0019 #include <cassert>
0020 #include <cstdint>
0021
0022 namespace clang {
0023 namespace markup {
0024
0025 using FIDMap = llvm::DenseMap<FileID, unsigned>;
0026
0027 inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
0028 FileID FID) {
0029 auto [I, Inserted] = FIDs.try_emplace(FID, V.size());
0030 if (Inserted)
0031 V.push_back(FID);
0032 return I->second;
0033 }
0034
0035 inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
0036 const SourceManager &SM, SourceLocation L) {
0037 FileID FID = SM.getFileID(SM.getExpansionLoc(L));
0038 return AddFID(FIDs, V, FID);
0039 }
0040
0041 inline unsigned GetFID(const FIDMap &FIDs, FileID FID) {
0042 FIDMap::const_iterator I = FIDs.find(FID);
0043 assert(I != FIDs.end());
0044 return I->second;
0045 }
0046
0047 inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM,
0048 SourceLocation L) {
0049 FileID FID = SM.getFileID(SM.getExpansionLoc(L));
0050 return GetFID(FIDs, FID);
0051 }
0052
0053 inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) {
0054 for (unsigned i = 0; i < indent; ++i)
0055 o << ' ';
0056 return o;
0057 }
0058
0059 inline raw_ostream &EmitPlistHeader(raw_ostream &o) {
0060 static const char *PlistHeader =
0061 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0062 "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
0063 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
0064 "<plist version=\"1.0\">\n";
0065 return o << PlistHeader;
0066 }
0067
0068 inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) {
0069 o << "<integer>";
0070 o << value;
0071 o << "</integer>";
0072 return o;
0073 }
0074
0075 inline raw_ostream &EmitString(raw_ostream &o, StringRef s) {
0076 o << "<string>";
0077 for (char c : s) {
0078 switch (c) {
0079 default:
0080 o << c;
0081 break;
0082 case '&':
0083 o << "&";
0084 break;
0085 case '<':
0086 o << "<";
0087 break;
0088 case '>':
0089 o << ">";
0090 break;
0091 case '\'':
0092 o << "'";
0093 break;
0094 case '\"':
0095 o << """;
0096 break;
0097 }
0098 }
0099 o << "</string>";
0100 return o;
0101 }
0102
0103 inline void EmitLocation(raw_ostream &o, const SourceManager &SM,
0104 SourceLocation L, const FIDMap &FM, unsigned indent) {
0105 if (L.isInvalid()) return;
0106
0107 FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM));
0108
0109 Indent(o, indent) << "<dict>\n";
0110 Indent(o, indent) << " <key>line</key>";
0111 EmitInteger(o, Loc.getExpansionLineNumber()) << '\n';
0112 Indent(o, indent) << " <key>col</key>";
0113 EmitInteger(o, Loc.getExpansionColumnNumber()) << '\n';
0114 Indent(o, indent) << " <key>file</key>";
0115 EmitInteger(o, GetFID(FM, SM, Loc)) << '\n';
0116 Indent(o, indent) << "</dict>\n";
0117 }
0118
0119 inline void EmitRange(raw_ostream &o, const SourceManager &SM,
0120 CharSourceRange R, const FIDMap &FM, unsigned indent) {
0121 if (R.isInvalid()) return;
0122
0123 assert(R.isCharRange() && "cannot handle a token range");
0124 Indent(o, indent) << "<array>\n";
0125 EmitLocation(o, SM, R.getBegin(), FM, indent + 1);
0126
0127
0128
0129
0130 EmitLocation(o, SM, R.getEnd().getLocWithOffset(-1), FM, indent + 1);
0131 Indent(o, indent) << "</array>\n";
0132 }
0133
0134 }
0135 }
0136
0137 #endif