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,
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
isAtStartOfLine - Return true if this token is at the start of a line.
SourceManager & getSourceManager() const
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
SourceManager & getSourceMgr() const
Defines the SourceManager interface.
bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, const Token &Tok) const
AvoidConcat - If printing PrevTok immediately followed by Tok would cause the two individual tokens t...
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
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)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
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)
HighlightMacros - This uses the macro table state from the end of the file, to reexpand macros and in...
void AddLineNumbers(Rewriter &R, FileID FID)
const LangOptions & getLangOpts() const
Token - This structure provides full information about a lexed token.
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)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords...
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)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Defines the clang::Preprocessor interface.
void InsertTextAfter(unsigned OrigOffset, StringRef Str)
InsertTextAfter - Insert some text at the specified point, where the offset in the buffer is specifie...
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)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Encodes a location in the source.
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
EscapeText - HTMLize a specified file so that special characters are are translated so that they are ...
bool InsertTextAfter(SourceLocation Loc, StringRef Str)
InsertTextAfter - Insert the specified string at the specified location in the original buffer...
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
DiagnosticsEngine & getDiagnostics() const
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
InsertText - Insert the specified string at the specified location in the original buffer...
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
void InsertTextBefore(unsigned OrigOffset, StringRef Str)
InsertTextBefore - Insert some text before the specified point, where the offset in the buffer is spe...
A diagnostic client that ignores all diagnostics.
detail::InMemoryDirectory::const_iterator E
const LangOptions & getLangOpts() const
Rewriter - This is the main interface to the rewrite buffers.
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
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)
HighlightRange - Highlight a range in the source code with the specified start/end tags...