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,
39 assert(SM.
getFileID(E) == FID &&
"B/E not in the same file!");
49 const char *BufferStart = SM.
getBufferData(FID, &Invalid).data();
54 BufferStart, StartTag, EndTag);
60 const char *BufferStart,
61 const char *StartTag,
const char *EndTag) {
68 bool HadOpenTag =
true;
70 unsigned LastNonWhiteSpace = B;
71 for (
unsigned i = B; i != E; ++i) {
72 switch (BufferStart[i]) {
102 LastNonWhiteSpace = i;
109 bool EscapeSpaces,
bool ReplaceTabs) {
112 const char*
C = Buf->getBufferStart();
113 const char* FileEnd = Buf->getBufferEnd();
115 assert (C <= FileEnd);
120 for (
unsigned FilePos = 0; C != FileEnd ; ++
C, ++FilePos) {
122 default: ++ColNo;
break;
141 unsigned NumSpaces = 8-(ColNo&7);
144 StringRef(
" " 145 " ", 6*NumSpaces));
147 RB.
ReplaceText(FilePos, 1, StringRef(
" ", NumSpaces));
171 unsigned len = s.size();
173 llvm::raw_string_ostream os(Str);
175 for (
unsigned i = 0 ; i < len; ++i) {
183 if (EscapeSpaces) os <<
" ";
190 for (
unsigned i = 0; i < 4; ++i)
193 for (
unsigned i = 0; i < 4; ++i)
201 case '<': os <<
"<";
break;
202 case '>': os <<
">";
break;
203 case '&': os <<
"&";
break;
211 unsigned B,
unsigned E) {
213 llvm::raw_svector_ostream OS(Str);
215 OS <<
"<tr class=\"codeline\" data-linenumber=\"" << LineNo <<
"\">" 216 <<
"<td class=\"num\" id=\"LN" << LineNo <<
"\">" << LineNo
217 <<
"</td><td class=\"line\">";
231 const char* FileBeg = Buf->getBufferStart();
232 const char* FileEnd = Buf->getBufferEnd();
233 const char*
C = FileBeg;
236 assert (C <= FileEnd);
239 unsigned FilePos = 0;
241 while (C != FileEnd) {
244 unsigned LineStartPos = FilePos;
245 unsigned LineEndPos = FileEnd - FileBeg;
247 assert (FilePos <= LineEndPos);
248 assert (C < FileEnd);
252 while (C != FileEnd) {
257 LineEndPos = FilePos++;
269 llvm::raw_string_ostream os(s);
270 os <<
"<table class=\"code\" data-fileid=\"" << FID.
getHashValue() <<
"\">\n";
279 const char* FileStart = Buf->getBufferStart();
280 const char* FileEnd = Buf->getBufferEnd();
286 llvm::raw_string_ostream os(s);
287 os <<
"<!doctype html>\n" 294 <style type="text/css"> 295 body { color:#000000; background-color:#ffffff } 296 body { font-family:Helvetica, sans-serif; font-size:10pt } 297 h1 { font-size:14pt } 298 .FileName { margin-top: 5px; margin-bottom: 5px; display: inline; } 299 .FileNav { margin-left: 5px; margin-right: 5px; display: inline; } 300 .FileNav a { text-decoration:none; font-size: larger; } 301 .divider { margin-top: 30px; margin-bottom: 30px; height: 15px; } 302 .divider { background-color: gray; } 303 .code { border-collapse:collapse; width:100%; } 304 .code { font-family: "Monospace", monospace; font-size:10pt } 305 .code { line-height: 1.2em } 306 .comment { color: green; font-style: oblique } 307 .keyword { color: blue } 308 .string_literal { color: red } 309 .directive { color: darkmagenta } 310 /* Macro expansions. */ 311 .expansion { display: none; } 312 .macro:hover .expansion { 314 border: 2px solid #FF0000; 316 background-color:#FFF0F0; 318 -webkit-border-radius:5px; 319 -webkit-box-shadow:1px 1px 7px #000; 321 box-shadow:1px 1px 7px #000; 334 border: 1px solid #b0b0b0; 336 box-shadow: 1px 1px 7px black; 337 background-color: #c0c0c0; 342 background-color:LemonChiffon; 343 /* Macros are position: relative to provide base for expansions. */ 347 .num { width:2.5em; padding-right:2ex; background-color:#eeeeee } 348 .num { text-align:right; font-size:8pt } 349 .num { color:#444444 } 350 .line { padding-left: 1ex; border-left: 3px solid #ccc } 351 .line { white-space: pre } 352 .msg { -webkit-box-shadow:1px 1px 7px #000 } 353 .msg { box-shadow:1px 1px 7px #000 } 354 .msg { -webkit-border-radius:5px } 355 .msg { border-radius:5px } 356 .msg { font-family:Helvetica, sans-serif; font-size:8pt } 358 .msg { padding:0.25em 1ex 0.25em 1ex } 359 .msg { margin-top:10px; margin-bottom:10px } 360 .msg { font-weight:bold } 361 .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap } 362 .msgT { padding:0x; spacing:0x } 363 .msgEvent { background-color:#fff8b4; color:#000000 } 364 .msgControl { background-color:#bbbbbb; color:#000000 } 365 .msgNote { background-color:#ddeeff; color:#000000 } 366 .mrange { background-color:#dfddf3 } 367 .mrange { border-bottom:1px solid #6F9DBE } 368 .PathIndex { font-weight: bold; padding:0px 5px; margin-right:5px; } 369 .PathIndex { -webkit-border-radius:8px } 370 .PathIndex { border-radius:8px } 371 .PathIndexEvent { background-color:#bfba87 } 372 .PathIndexControl { background-color:#8c8c8c } 373 .PathNav a { text-decoration:none; font-size: larger } 374 .CodeInsertionHint { font-weight: bold; background-color: #10dd10 } 375 .CodeRemovalHint { background-color:#de1010 } 376 .CodeRemovalHint { border-bottom:1px solid #6F9DBE } 377 .selected{ background-color:orange !important; } 383 border-collapse: collapse; border-spacing: 0px; 394 input.spoilerhider + label { 396 text-decoration: underline; 402 input.spoilerhider ~ .spoiler { 408 input.spoilerhider:checked + label + .spoiler{ 431 const llvm::MemoryBuffer *FromFile = SM.
getBuffer(FID);
433 const char *BufferStart = L.
getBuffer().data();
437 L.SetCommentRetentionState(
true);
442 L.LexFromRawLexer(Tok);
451 case tok::identifier:
452 llvm_unreachable(
"tok::identifier in raw lexing mode!");
453 case tok::raw_identifier: {
459 if (Tok.
isNot(tok::identifier))
461 "<span class='keyword'>",
"</span>");
466 "<span class='comment'>",
"</span>");
468 case tok::utf8_string_literal:
474 case tok::wide_string_literal:
475 case tok::utf16_string_literal:
476 case tok::utf32_string_literal:
481 case tok::string_literal:
484 "<span class='string_literal'>",
"</span>");
493 unsigned TokEnd = TokOffs+TokLen;
494 L.LexFromRawLexer(Tok);
497 L.LexFromRawLexer(Tok);
502 "<span class='directive'>",
"</span>");
509 L.LexFromRawLexer(Tok);
520 std::vector<Token> TokenStream;
522 const llvm::MemoryBuffer *FromFile = SM.
getBuffer(FID);
529 L.LexFromRawLexer(Tok);
539 if (Tok.
is(tok::hashhash))
545 if (Tok.
is(tok::raw_identifier))
548 TokenStream.push_back(Tok);
564 TmpPP.setDiagnostics(TmpDiags);
567 TmpPP.SetCommentRetentionState(
false,
false);
571 bool PragmasPreviouslyEnabled = TmpPP.getPragmasEnabled();
572 TmpPP.setPragmasEnabled(
false);
576 TmpPP.EnterTokenStream(TokenStream,
false);
602 "Start and end of expansion must be in the same ultimate file!");
604 std::string Expansion =
EscapeText(TmpPP.getSpelling(Tok));
605 unsigned LineLen = Expansion.size();
623 LineLen -= Expansion.size();
632 Expansion +=
EscapeText(TmpPP.getSpelling(Tok));
633 LineLen += Expansion.size();
635 PrevPrevTok = PrevTok;
643 Expansion =
"<span class='expansion'>" + Expansion +
"</span></span>";
650 TmpPP.setDiagnostics(*OldDiags);
651 TmpPP.setPragmasEnabled(PragmasPreviouslyEnabled);
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
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)) {...
Defines the SourceManager interface.
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
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...
tok::TokenKind getKind() const
SourceLocation getBegin() const
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)
unsigned getHashValue() const
Token - This structure provides full information about a lexed token.
void setKind(tok::TokenKind K)
const LangOptions & getLangOpts() const
SourceManager & getSourceMgr() const
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
Concrete class used by the front-end to report problems and issues.
StringRef getBuffer() const
Gets source code buffer.
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords...
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
Represents a character-granular source range.
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 ...
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
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...
SourceManager & getSourceManager() const
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
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...
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
InsertText - Insert the specified string at the specified location in the original buffer...
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isNot(tok::TokenKind K) const
void InsertTextBefore(unsigned OrigOffset, StringRef Str)
InsertTextBefore - Insert some text before the specified point, where the offset in the buffer is spe...
Dataflow Directional Tag Classes.
A diagnostic client that ignores all diagnostics.
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, StringRef title)
unsigned getLength() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
const LangOptions & getLangOpts() const
SourceLocation getEnd() const
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...
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
Rewriter - This is the main interface to the rewrite buffers.
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
DiagnosticsEngine & getDiagnostics() const
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, const char *StartTag, const char *EndTag, bool IsTokenRange=true)
HighlightRange - Highlight a range in the source code with the specified start/end tags...
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.