20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
33 const char *StartTag,
const char *EndTag) {
38 assert(SM.
getFileID(E) == FID &&
"B/E not in the same file!");
47 const char *BufferStart = SM.
getBufferData(FID, &Invalid).data();
52 BufferStart, StartTag, EndTag);
58 const char *BufferStart,
59 const char *StartTag,
const char *EndTag) {
66 bool HadOpenTag =
true;
68 unsigned LastNonWhiteSpace = B;
69 for (
unsigned i = B; i != E; ++i) {
70 switch (BufferStart[i]) {
100 LastNonWhiteSpace = i;
107 bool EscapeSpaces,
bool ReplaceTabs) {
110 const char*
C = Buf->getBufferStart();
111 const char* FileEnd = Buf->getBufferEnd();
113 assert (C <= FileEnd);
118 for (
unsigned FilePos = 0; C != FileEnd ; ++
C, ++FilePos) {
120 default: ++ColNo;
break;
139 unsigned NumSpaces = 8-(ColNo&7);
142 StringRef(
" "
143 " ", 6*NumSpaces));
145 RB.
ReplaceText(FilePos, 1, StringRef(
" ", NumSpaces));
169 unsigned len = s.size();
171 llvm::raw_string_ostream os(Str);
173 for (
unsigned i = 0 ; i < len; ++i) {
181 if (EscapeSpaces) os <<
" ";
188 for (
unsigned i = 0; i < 4; ++i)
191 for (
unsigned i = 0; i < 4; ++i)
199 case '<': os <<
"<";
break;
200 case '>': os <<
">";
break;
201 case '&': os <<
"&";
break;
209 unsigned B,
unsigned E) {
211 llvm::raw_svector_ostream OS(Str);
213 OS <<
"<tr><td class=\"num\" id=\"LN"
215 << LineNo <<
"</td><td class=\"line\">";
229 const char* FileBeg = Buf->getBufferStart();
230 const char* FileEnd = Buf->getBufferEnd();
231 const char*
C = FileBeg;
234 assert (C <= FileEnd);
237 unsigned FilePos = 0;
239 while (C != FileEnd) {
242 unsigned LineStartPos = FilePos;
243 unsigned LineEndPos = FileEnd - FileBeg;
245 assert (FilePos <= LineEndPos);
246 assert (C < FileEnd);
250 while (C != FileEnd) {
255 LineEndPos = FilePos++;
274 const char* FileStart = Buf->getBufferStart();
275 const char* FileEnd = Buf->getBufferEnd();
281 llvm::raw_string_ostream os(s);
282 os <<
"<!doctype html>\n"
288 os <<
"<style type=\"text/css\">\n"
289 " body { color:#000000; background-color:#ffffff }\n"
290 " body { font-family:Helvetica, sans-serif; font-size:10pt }\n"
291 " h1 { font-size:14pt }\n"
292 " .code { border-collapse:collapse; width:100%; }\n"
293 " .code { font-family: \"Monospace\", monospace; font-size:10pt }\n"
294 " .code { line-height: 1.2em }\n"
295 " .comment { color: green; font-style: oblique }\n"
296 " .keyword { color: blue }\n"
297 " .string_literal { color: red }\n"
298 " .directive { color: darkmagenta }\n"
300 " .expansion { display: none; }\n"
301 " .macro:hover .expansion { display: block; border: 2px solid #FF0000; "
302 "padding: 2px; background-color:#FFF0F0; font-weight: normal; "
303 " -webkit-border-radius:5px; -webkit-box-shadow:1px 1px 7px #000; "
304 "position: absolute; top: -1em; left:10em; z-index: 1 } \n"
305 " .macro { color: darkmagenta; background-color:LemonChiffon;"
307 " position: relative }\n"
308 " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n"
309 " .num { text-align:right; font-size:8pt }\n"
310 " .num { color:#444444 }\n"
311 " .line { padding-left: 1ex; border-left: 3px solid #ccc }\n"
312 " .line { white-space: pre }\n"
313 " .msg { -webkit-box-shadow:1px 1px 7px #000 }\n"
314 " .msg { -webkit-border-radius:5px }\n"
315 " .msg { font-family:Helvetica, sans-serif; font-size:8pt }\n"
316 " .msg { float:left }\n"
317 " .msg { padding:0.25em 1ex 0.25em 1ex }\n"
318 " .msg { margin-top:10px; margin-bottom:10px }\n"
319 " .msg { font-weight:bold }\n"
320 " .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }\n"
321 " .msgT { padding:0x; spacing:0x }\n"
322 " .msgEvent { background-color:#fff8b4; color:#000000 }\n"
323 " .msgControl { background-color:#bbbbbb; color:#000000 }\n"
324 " .mrange { background-color:#dfddf3 }\n"
325 " .mrange { border-bottom:1px solid #6F9DBE }\n"
326 " .PathIndex { font-weight: bold; padding:0px 5px; "
327 "margin-right:5px; }\n"
328 " .PathIndex { -webkit-border-radius:8px }\n"
329 " .PathIndexEvent { background-color:#bfba87 }\n"
330 " .PathIndexControl { background-color:#8c8c8c }\n"
331 " .PathNav a { text-decoration:none; font-size: larger }\n"
332 " .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n"
333 " .CodeRemovalHint { background-color:#de1010 }\n"
334 " .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n"
335 " table.simpletable {\n"
339 " border-collapse: collapse; border-spacing: 0px;\n"
342 " text-align:right; font-weight:bold; color:#444444;\n"
343 " padding-right:2ex; }\n"
344 "</style>\n</head>\n<body>";
361 const llvm::MemoryBuffer *FromFile = SM.
getBuffer(FID);
363 const char *BufferStart = L.
getBuffer().data();
367 L.SetCommentRetentionState(
true);
372 L.LexFromRawLexer(Tok);
381 case tok::identifier:
382 llvm_unreachable(
"tok::identifier in raw lexing mode!");
383 case tok::raw_identifier: {
389 if (Tok.
isNot(tok::identifier))
391 "<span class='keyword'>",
"</span>");
396 "<span class='comment'>",
"</span>");
398 case tok::utf8_string_literal:
403 case tok::wide_string_literal:
404 case tok::utf16_string_literal:
405 case tok::utf32_string_literal:
410 case tok::string_literal:
413 "<span class='string_literal'>",
"</span>");
422 unsigned TokEnd = TokOffs+TokLen;
423 L.LexFromRawLexer(Tok);
426 L.LexFromRawLexer(Tok);
431 "<span class='directive'>",
"</span>");
438 L.LexFromRawLexer(Tok);
449 std::vector<Token> TokenStream;
451 const llvm::MemoryBuffer *FromFile = SM.
getBuffer(FID);
458 L.LexFromRawLexer(Tok);
468 if (Tok.
is(tok::hashhash))
474 if (Tok.
is(tok::raw_identifier))
477 TokenStream.push_back(Tok);
493 TmpPP.setDiagnostics(TmpDiags);
496 TmpPP.SetCommentRetentionState(
false,
false);
500 bool PragmasPreviouslyEnabled = TmpPP.getPragmasEnabled();
501 TmpPP.setPragmasEnabled(
false);
505 TmpPP.EnterTokenStream(&TokenStream[0], TokenStream.size(),
false,
false);
522 std::pair<SourceLocation, SourceLocation> LLoc =
531 assert(SM.
getFileID(LLoc.second) == FID &&
532 "Start and end of expansion must be in the same ultimate file!");
534 std::string Expansion =
EscapeText(TmpPP.getSpelling(Tok));
535 unsigned LineLen = Expansion.size();
553 LineLen -= Expansion.size();
562 Expansion +=
EscapeText(TmpPP.getSpelling(Tok));
563 LineLen += Expansion.size();
565 PrevPrevTok = PrevTok;
573 Expansion =
"<span class='expansion'>" + Expansion +
"</span></span>";
576 "<span class='macro'>", Expansion.c_str());
580 TmpPP.setDiagnostics(*OldDiags);
581 TmpPP.setPragmasEnabled(PragmasPreviouslyEnabled);
bool isAtStartOfLine() const
SourceManager & getSourceManager() const
SourceManager & getSourceMgr() const
Defines the SourceManager interface.
bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, const Token &Tok) const
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
StringRef getBuffer() const
Gets source code buffer.
RewriteBuffer & getEditBuffer(FileID FID)
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
std::pair< SourceLocation, SourceLocation > getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo, unsigned B, unsigned E)
void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP)
void AddLineNumbers(Rewriter &R, FileID FID)
const LangOptions & getLangOpts() const
void setKind(tok::TokenKind K)
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
Concrete class used by the front-end to report problems and issues.
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP)
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
tok::TokenKind getKind() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Defines the clang::Preprocessor interface.
void InsertTextAfter(unsigned OrigOffset, StringRef Str)
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isNot(tok::TokenKind K) const
void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, const char *title=nullptr)
void ReplaceText(unsigned OrigOffset, unsigned OrigLength, StringRef NewStr)
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
bool InsertTextAfter(SourceLocation Loc, StringRef Str)
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
bool is(tok::TokenKind K) const
DiagnosticsEngine & getDiagnostics() const
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
void InsertTextBefore(unsigned OrigOffset, StringRef Str)
A diagnostic client that ignores all diagnostics.
const LangOptions & getLangOpts() const
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
unsigned getLength() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, const char *StartTag, const char *EndTag)