clang  14.0.0git
HTMLRewrite.cpp
Go to the documentation of this file.
1 //== HTMLRewrite.cpp - Translate source code into prettified HTML --*- C++ -*-//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the HTMLRewriter class, which is used to translate the
10 // text of a source file into prettified HTML.
11 //
12 //===----------------------------------------------------------------------===//
13 
16 #include "clang/Lex/Preprocessor.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <memory>
24 using namespace clang;
25 
26 
27 /// HighlightRange - Highlight a range in the source code with the specified
28 /// start/end tags. B/E must be in the same file. This ensures that
29 /// start/end tags are placed at the start/end of each line if the range is
30 /// multiline.
32  const char *StartTag, const char *EndTag,
33  bool IsTokenRange) {
35  B = SM.getExpansionLoc(B);
36  E = SM.getExpansionLoc(E);
37  FileID FID = SM.getFileID(B);
38  assert(SM.getFileID(E) == FID && "B/E not in the same file!");
39 
40  unsigned BOffset = SM.getFileOffset(B);
41  unsigned EOffset = SM.getFileOffset(E);
42 
43  // Include the whole end token in the range.
44  if (IsTokenRange)
45  EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr(), R.getLangOpts());
46 
47  bool Invalid = false;
48  const char *BufferStart = SM.getBufferData(FID, &Invalid).data();
49  if (Invalid)
50  return;
51 
52  HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
53  BufferStart, StartTag, EndTag);
54 }
55 
56 /// HighlightRange - This is the same as the above method, but takes
57 /// decomposed file locations.
58 void html::HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E,
59  const char *BufferStart,
60  const char *StartTag, const char *EndTag) {
61  // Insert the tag at the absolute start/end of the range.
62  RB.InsertTextAfter(B, StartTag);
63  RB.InsertTextBefore(E, EndTag);
64 
65  // Scan the range to see if there is a \r or \n. If so, and if the line is
66  // not blank, insert tags on that line as well.
67  bool HadOpenTag = true;
68 
69  unsigned LastNonWhiteSpace = B;
70  for (unsigned i = B; i != E; ++i) {
71  switch (BufferStart[i]) {
72  case '\r':
73  case '\n':
74  // Okay, we found a newline in the range. If we have an open tag, we need
75  // to insert a close tag at the first non-whitespace before the newline.
76  if (HadOpenTag)
77  RB.InsertTextBefore(LastNonWhiteSpace+1, EndTag);
78 
79  // Instead of inserting an open tag immediately after the newline, we
80  // wait until we see a non-whitespace character. This prevents us from
81  // inserting tags around blank lines, and also allows the open tag to
82  // be put *after* whitespace on a non-blank line.
83  HadOpenTag = false;
84  break;
85  case '\0':
86  case ' ':
87  case '\t':
88  case '\f':
89  case '\v':
90  // Ignore whitespace.
91  break;
92 
93  default:
94  // If there is no tag open, do it now.
95  if (!HadOpenTag) {
96  RB.InsertTextAfter(i, StartTag);
97  HadOpenTag = true;
98  }
99 
100  // Remember this character.
101  LastNonWhiteSpace = i;
102  break;
103  }
104  }
105 }
106 
108  bool EscapeSpaces, bool ReplaceTabs) {
109 
110  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
111  const char* C = Buf.getBufferStart();
112  const char* FileEnd = Buf.getBufferEnd();
113 
114  assert (C <= FileEnd);
115 
116  RewriteBuffer &RB = R.getEditBuffer(FID);
117 
118  unsigned ColNo = 0;
119  for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) {
120  switch (*C) {
121  default: ++ColNo; break;
122  case '\n':
123  case '\r':
124  ColNo = 0;
125  break;
126 
127  case ' ':
128  if (EscapeSpaces)
129  RB.ReplaceText(FilePos, 1, "&nbsp;");
130  ++ColNo;
131  break;
132  case '\f':
133  RB.ReplaceText(FilePos, 1, "<hr>");
134  ColNo = 0;
135  break;
136 
137  case '\t': {
138  if (!ReplaceTabs)
139  break;
140  unsigned NumSpaces = 8-(ColNo&7);
141  if (EscapeSpaces)
142  RB.ReplaceText(FilePos, 1,
143  StringRef("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
144  "&nbsp;&nbsp;&nbsp;", 6*NumSpaces));
145  else
146  RB.ReplaceText(FilePos, 1, StringRef(" ", NumSpaces));
147  ColNo += NumSpaces;
148  break;
149  }
150  case '<':
151  RB.ReplaceText(FilePos, 1, "&lt;");
152  ++ColNo;
153  break;
154 
155  case '>':
156  RB.ReplaceText(FilePos, 1, "&gt;");
157  ++ColNo;
158  break;
159 
160  case '&':
161  RB.ReplaceText(FilePos, 1, "&amp;");
162  ++ColNo;
163  break;
164  }
165  }
166 }
167 
168 std::string html::EscapeText(StringRef s, bool EscapeSpaces, bool ReplaceTabs) {
169 
170  unsigned len = s.size();
171  std::string Str;
172  llvm::raw_string_ostream os(Str);
173 
174  for (unsigned i = 0 ; i < len; ++i) {
175 
176  char c = s[i];
177  switch (c) {
178  default:
179  os << c; break;
180 
181  case ' ':
182  if (EscapeSpaces) os << "&nbsp;";
183  else os << ' ';
184  break;
185 
186  case '\t':
187  if (ReplaceTabs) {
188  if (EscapeSpaces)
189  for (unsigned i = 0; i < 4; ++i)
190  os << "&nbsp;";
191  else
192  for (unsigned i = 0; i < 4; ++i)
193  os << " ";
194  }
195  else
196  os << c;
197 
198  break;
199 
200  case '<': os << "&lt;"; break;
201  case '>': os << "&gt;"; break;
202  case '&': os << "&amp;"; break;
203  }
204  }
205 
206  return os.str();
207 }
208 
209 static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo,
210  unsigned B, unsigned E) {
211  SmallString<256> Str;
212  llvm::raw_svector_ostream OS(Str);
213 
214  OS << "<tr class=\"codeline\" data-linenumber=\"" << LineNo << "\">"
215  << "<td class=\"num\" id=\"LN" << LineNo << "\">" << LineNo
216  << "</td><td class=\"line\">";
217 
218  if (B == E) { // Handle empty lines.
219  OS << " </td></tr>";
220  RB.InsertTextBefore(B, OS.str());
221  } else {
222  RB.InsertTextBefore(B, OS.str());
223  RB.InsertTextBefore(E, "</td></tr>");
224  }
225 }
226 
228 
229  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
230  const char* FileBeg = Buf.getBufferStart();
231  const char* FileEnd = Buf.getBufferEnd();
232  const char* C = FileBeg;
233  RewriteBuffer &RB = R.getEditBuffer(FID);
234 
235  assert (C <= FileEnd);
236 
237  unsigned LineNo = 0;
238  unsigned FilePos = 0;
239 
240  while (C != FileEnd) {
241 
242  ++LineNo;
243  unsigned LineStartPos = FilePos;
244  unsigned LineEndPos = FileEnd - FileBeg;
245 
246  assert (FilePos <= LineEndPos);
247  assert (C < FileEnd);
248 
249  // Scan until the newline (or end-of-file).
250 
251  while (C != FileEnd) {
252  char c = *C;
253  ++C;
254 
255  if (c == '\n') {
256  LineEndPos = FilePos++;
257  break;
258  }
259 
260  ++FilePos;
261  }
262 
263  AddLineNumber(RB, LineNo, LineStartPos, LineEndPos);
264  }
265 
266  // Add one big table tag that surrounds all of the code.
267  std::string s;
268  llvm::raw_string_ostream os(s);
269  os << "<table class=\"code\" data-fileid=\"" << FID.getHashValue() << "\">\n";
270  RB.InsertTextBefore(0, os.str());
271  RB.InsertTextAfter(FileEnd - FileBeg, "</table>");
272 }
273 
275  StringRef title) {
276 
277  llvm::MemoryBufferRef Buf = R.getSourceMgr().getBufferOrFake(FID);
278  const char* FileStart = Buf.getBufferStart();
279  const char* FileEnd = Buf.getBufferEnd();
280 
282  SourceLocation EndLoc = StartLoc.getLocWithOffset(FileEnd-FileStart);
283 
284  std::string s;
285  llvm::raw_string_ostream os(s);
286  os << "<!doctype html>\n" // Use HTML 5 doctype
287  "<html>\n<head>\n";
288 
289  if (!title.empty())
290  os << "<title>" << html::EscapeText(title) << "</title>\n";
291 
292  os << R"<<<(
293 <style type="text/css">
294 body { color:#000000; background-color:#ffffff }
295 body { font-family:Helvetica, sans-serif; font-size:10pt }
296 h1 { font-size:14pt }
297 .FileName { margin-top: 5px; margin-bottom: 5px; display: inline; }
298 .FileNav { margin-left: 5px; margin-right: 5px; display: inline; }
299 .FileNav a { text-decoration:none; font-size: larger; }
300 .divider { margin-top: 30px; margin-bottom: 30px; height: 15px; }
301 .divider { background-color: gray; }
302 .code { border-collapse:collapse; width:100%; }
303 .code { font-family: "Monospace", monospace; font-size:10pt }
304 .code { line-height: 1.2em }
305 .comment { color: green; font-style: oblique }
306 .keyword { color: blue }
307 .string_literal { color: red }
308 .directive { color: darkmagenta }
309 
310 /* Macros and variables could have pop-up notes hidden by default.
311  - Macro pop-up: expansion of the macro
312  - Variable pop-up: value (table) of the variable */
313 .macro_popup, .variable_popup { display: none; }
314 
315 /* Pop-up appears on mouse-hover event. */
316 .macro:hover .macro_popup, .variable:hover .variable_popup {
317  display: block;
318  padding: 2px;
319  -webkit-border-radius:5px;
320  -webkit-box-shadow:1px 1px 7px #000;
321  border-radius:5px;
322  box-shadow:1px 1px 7px #000;
323  position: absolute;
324  top: -1em;
325  left:10em;
326  z-index: 1
327 }
328 
329 .macro_popup {
330  border: 2px solid red;
331  background-color:#FFF0F0;
332  font-weight: normal;
333 }
334 
335 .variable_popup {
336  border: 2px solid blue;
337  background-color:#F0F0FF;
338  font-weight: bold;
339  font-family: Helvetica, sans-serif;
340  font-size: 9pt;
341 }
342 
343 /* Pop-up notes needs a relative position as a base where they pops up. */
344 .macro, .variable {
345  background-color: PaleGoldenRod;
346  position: relative;
347 }
348 .macro { color: DarkMagenta; }
349 
350 #tooltiphint {
351  position: fixed;
352  width: 50em;
353  margin-left: -25em;
354  left: 50%;
355  padding: 10px;
356  border: 1px solid #b0b0b0;
357  border-radius: 2px;
358  box-shadow: 1px 1px 7px black;
359  background-color: #c0c0c0;
360  z-index: 2;
361 }
362 
363 .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }
364 .num { text-align:right; font-size:8pt }
365 .num { color:#444444 }
366 .line { padding-left: 1ex; border-left: 3px solid #ccc }
367 .line { white-space: pre }
368 .msg { -webkit-box-shadow:1px 1px 7px #000 }
369 .msg { box-shadow:1px 1px 7px #000 }
370 .msg { -webkit-border-radius:5px }
371 .msg { border-radius:5px }
372 .msg { font-family:Helvetica, sans-serif; font-size:8pt }
373 .msg { float:left }
374 .msg { position:relative }
375 .msg { padding:0.25em 1ex 0.25em 1ex }
376 .msg { margin-top:10px; margin-bottom:10px }
377 .msg { font-weight:bold }
378 .msg { max-width:60em; word-wrap: break-word; white-space: pre-wrap }
379 .msgT { padding:0x; spacing:0x }
380 .msgEvent { background-color:#fff8b4; color:#000000 }
381 .msgControl { background-color:#bbbbbb; color:#000000 }
382 .msgNote { background-color:#ddeeff; color:#000000 }
383 .mrange { background-color:#dfddf3 }
384 .mrange { border-bottom:1px solid #6F9DBE }
385 .PathIndex { font-weight: bold; padding:0px 5px; margin-right:5px; }
386 .PathIndex { -webkit-border-radius:8px }
387 .PathIndex { border-radius:8px }
388 .PathIndexEvent { background-color:#bfba87 }
389 .PathIndexControl { background-color:#8c8c8c }
390 .PathIndexPopUp { background-color: #879abc; }
391 .PathNav a { text-decoration:none; font-size: larger }
392 .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }
393 .CodeRemovalHint { background-color:#de1010 }
394 .CodeRemovalHint { border-bottom:1px solid #6F9DBE }
395 .msg.selected{ background-color:orange !important; }
396 
397 table.simpletable {
398  padding: 5px;
399  font-size:12pt;
400  margin:20px;
401  border-collapse: collapse; border-spacing: 0px;
402 }
403 td.rowname {
404  text-align: right;
405  vertical-align: top;
406  font-weight: bold;
407  color:#444444;
408  padding-right:2ex;
409 }
410 
411 /* Hidden text. */
412 input.spoilerhider + label {
413  cursor: pointer;
414  text-decoration: underline;
415  display: block;
416 }
417 input.spoilerhider {
418  display: none;
419 }
420 input.spoilerhider ~ .spoiler {
421  overflow: hidden;
422  margin: 10px auto 0;
423  height: 0;
424  opacity: 0;
425 }
426 input.spoilerhider:checked + label + .spoiler{
427  height: auto;
428  opacity: 1;
429 }
430 </style>
431 </head>
432 <body>)<<<";
433 
434  // Generate header
435  R.InsertTextBefore(StartLoc, os.str());
436  // Generate footer
437 
438  R.InsertTextAfter(EndLoc, "</body></html>\n");
439 }
440 
441 /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
442 /// information about keywords, macro expansions etc. This uses the macro
443 /// table state from the end of the file, so it won't be perfectly perfect,
444 /// but it will be reasonably close.
445 void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
446  RewriteBuffer &RB = R.getEditBuffer(FID);
447 
448  const SourceManager &SM = PP.getSourceManager();
449  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
450  Lexer L(FID, FromFile, SM, PP.getLangOpts());
451  const char *BufferStart = L.getBuffer().data();
452 
453  // Inform the preprocessor that we want to retain comments as tokens, so we
454  // can highlight them.
455  L.SetCommentRetentionState(true);
456 
457  // Lex all the tokens in raw mode, to avoid entering #includes or expanding
458  // macros.
459  Token Tok;
460  L.LexFromRawLexer(Tok);
461 
462  while (Tok.isNot(tok::eof)) {
463  // Since we are lexing unexpanded tokens, all tokens are from the main
464  // FileID.
465  unsigned TokOffs = SM.getFileOffset(Tok.getLocation());
466  unsigned TokLen = Tok.getLength();
467  switch (Tok.getKind()) {
468  default: break;
469  case tok::identifier:
470  llvm_unreachable("tok::identifier in raw lexing mode!");
471  case tok::raw_identifier: {
472  // Fill in Result.IdentifierInfo and update the token kind,
473  // looking up the identifier in the identifier table.
474  PP.LookUpIdentifierInfo(Tok);
475 
476  // If this is a pp-identifier, for a keyword, highlight it as such.
477  if (Tok.isNot(tok::identifier))
478  HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
479  "<span class='keyword'>", "</span>");
480  break;
481  }
482  case tok::comment:
483  HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
484  "<span class='comment'>", "</span>");
485  break;
486  case tok::utf8_string_literal:
487  // Chop off the u part of u8 prefix
488  ++TokOffs;
489  --TokLen;
490  // FALL THROUGH to chop the 8
491  LLVM_FALLTHROUGH;
492  case tok::wide_string_literal:
493  case tok::utf16_string_literal:
494  case tok::utf32_string_literal:
495  // Chop off the L, u, U or 8 prefix
496  ++TokOffs;
497  --TokLen;
498  LLVM_FALLTHROUGH;
499  case tok::string_literal:
500  // FIXME: Exclude the optional ud-suffix from the highlighted range.
501  HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
502  "<span class='string_literal'>", "</span>");
503  break;
504  case tok::hash: {
505  // If this is a preprocessor directive, all tokens to end of line are too.
506  if (!Tok.isAtStartOfLine())
507  break;
508 
509  // Eat all of the tokens until we get to the next one at the start of
510  // line.
511  unsigned TokEnd = TokOffs+TokLen;
512  L.LexFromRawLexer(Tok);
513  while (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
514  TokEnd = SM.getFileOffset(Tok.getLocation())+Tok.getLength();
515  L.LexFromRawLexer(Tok);
516  }
517 
518  // Find end of line. This is a hack.
519  HighlightRange(RB, TokOffs, TokEnd, BufferStart,
520  "<span class='directive'>", "</span>");
521 
522  // Don't skip the next token.
523  continue;
524  }
525  }
526 
527  L.LexFromRawLexer(Tok);
528  }
529 }
530 
531 /// HighlightMacros - This uses the macro table state from the end of the
532 /// file, to re-expand macros and insert (into the HTML) information about the
533 /// macro expansions. This won't be perfectly perfect, but it will be
534 /// reasonably close.
535 void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
536  // Re-lex the raw token stream into a token buffer.
537  const SourceManager &SM = PP.getSourceManager();
538  std::vector<Token> TokenStream;
539 
540  llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(FID);
541  Lexer L(FID, FromFile, SM, PP.getLangOpts());
542 
543  // Lex all the tokens in raw mode, to avoid entering #includes or expanding
544  // macros.
545  while (1) {
546  Token Tok;
547  L.LexFromRawLexer(Tok);
548 
549  // If this is a # at the start of a line, discard it from the token stream.
550  // We don't want the re-preprocess step to see #defines, #includes or other
551  // preprocessor directives.
552  if (Tok.is(tok::hash) && Tok.isAtStartOfLine())
553  continue;
554 
555  // If this is a ## token, change its kind to unknown so that repreprocessing
556  // it will not produce an error.
557  if (Tok.is(tok::hashhash))
558  Tok.setKind(tok::unknown);
559 
560  // If this raw token is an identifier, the raw lexer won't have looked up
561  // the corresponding identifier info for it. Do this now so that it will be
562  // macro expanded when we re-preprocess it.
563  if (Tok.is(tok::raw_identifier))
564  PP.LookUpIdentifierInfo(Tok);
565 
566  TokenStream.push_back(Tok);
567 
568  if (Tok.is(tok::eof)) break;
569  }
570 
571  // Temporarily change the diagnostics object so that we ignore any generated
572  // diagnostics from this pass.
576 
577  // FIXME: This is a huge hack; we reuse the input preprocessor because we want
578  // its state, but we aren't actually changing it (we hope). This should really
579  // construct a copy of the preprocessor.
580  Preprocessor &TmpPP = const_cast<Preprocessor&>(PP);
581  DiagnosticsEngine *OldDiags = &TmpPP.getDiagnostics();
582  TmpPP.setDiagnostics(TmpDiags);
583 
584  // Inform the preprocessor that we don't want comments.
585  TmpPP.SetCommentRetentionState(false, false);
586 
587  // We don't want pragmas either. Although we filtered out #pragma, removing
588  // _Pragma and __pragma is much harder.
589  bool PragmasPreviouslyEnabled = TmpPP.getPragmasEnabled();
590  TmpPP.setPragmasEnabled(false);
591 
592  // Enter the tokens we just lexed. This will cause them to be macro expanded
593  // but won't enter sub-files (because we removed #'s).
594  TmpPP.EnterTokenStream(TokenStream, false, /*IsReinject=*/false);
595 
596  TokenConcatenation ConcatInfo(TmpPP);
597 
598  // Lex all the tokens.
599  Token Tok;
600  TmpPP.Lex(Tok);
601  while (Tok.isNot(tok::eof)) {
602  // Ignore non-macro tokens.
603  if (!Tok.getLocation().isMacroID()) {
604  TmpPP.Lex(Tok);
605  continue;
606  }
607 
608  // Okay, we have the first token of a macro expansion: highlight the
609  // expansion by inserting a start tag before the macro expansion and
610  // end tag after it.
611  CharSourceRange LLoc = SM.getExpansionRange(Tok.getLocation());
612 
613  // Ignore tokens whose instantiation location was not the main file.
614  if (SM.getFileID(LLoc.getBegin()) != FID) {
615  TmpPP.Lex(Tok);
616  continue;
617  }
618 
619  assert(SM.getFileID(LLoc.getEnd()) == FID &&
620  "Start and end of expansion must be in the same ultimate file!");
621 
622  std::string Expansion = EscapeText(TmpPP.getSpelling(Tok));
623  unsigned LineLen = Expansion.size();
624 
625  Token PrevPrevTok;
626  Token PrevTok = Tok;
627  // Okay, eat this token, getting the next one.
628  TmpPP.Lex(Tok);
629 
630  // Skip all the rest of the tokens that are part of this macro
631  // instantiation. It would be really nice to pop up a window with all the
632  // spelling of the tokens or something.
633  while (!Tok.is(tok::eof) &&
634  SM.getExpansionLoc(Tok.getLocation()) == LLoc.getBegin()) {
635  // Insert a newline if the macro expansion is getting large.
636  if (LineLen > 60) {
637  Expansion += "<br>";
638  LineLen = 0;
639  }
640 
641  LineLen -= Expansion.size();
642 
643  // If the tokens were already space separated, or if they must be to avoid
644  // them being implicitly pasted, add a space between them.
645  if (Tok.hasLeadingSpace() ||
646  ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok))
647  Expansion += ' ';
648 
649  // Escape any special characters in the token text.
650  Expansion += EscapeText(TmpPP.getSpelling(Tok));
651  LineLen += Expansion.size();
652 
653  PrevPrevTok = PrevTok;
654  PrevTok = Tok;
655  TmpPP.Lex(Tok);
656  }
657 
658  // Insert the 'macro_popup' as the end tag, so that multi-line macros all
659  // get highlighted.
660  Expansion = "<span class='macro_popup'>" + Expansion + "</span></span>";
661 
662  HighlightRange(R, LLoc.getBegin(), LLoc.getEnd(), "<span class='macro'>",
663  Expansion.c_str(), LLoc.isTokenRange());
664  }
665 
666  // Restore the preprocessor's old state.
667  TmpPP.setDiagnostics(*OldDiags);
668  TmpPP.setPragmasEnabled(PragmasPreviouslyEnabled);
669 }
clang::RewriteBuffer::InsertTextAfter
void InsertTextAfter(unsigned OrigOffset, StringRef Str)
InsertTextAfter - Insert some text at the specified point, where the offset in the buffer is specifie...
Definition: RewriteBuffer.h:81
clang::Token::hasLeadingSpace
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
Definition: Token.h:272
clang::Lexer::SetCommentRetentionState
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
Definition: Lexer.h:231
clang::Rewriter::getEditBuffer
RewriteBuffer & getEditBuffer(FileID FID)
getEditBuffer - This is like getRewriteBufferFor, but always returns a buffer, and allows you to writ...
Definition: Rewriter.cpp:240
clang::CharSourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:285
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::Preprocessor::Lex
void Lex(Token &Result)
Lex the next token for this preprocessor.
Definition: Preprocessor.cpp:888
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::SourceLocation::getLocWithOffset
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
Definition: SourceLocation.h:136
clang::DiagnosticsEngine::getDiagnosticOptions
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
Definition: Diagnostic.h:555
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::RewriteBuffer::ReplaceText
void ReplaceText(unsigned OrigOffset, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string.
Definition: Rewriter.cpp:130
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
clang::Token::isAtStartOfLine
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
Definition: Token.h:268
clang::html::HighlightMacros
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...
Definition: HTMLRewrite.cpp:395
SourceManager.h
TokenConcatenation.h
clang::TokenConcatenation
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
Definition: TokenConcatenation.h:30
clang::Rewriter::getSourceMgr
SourceManager & getSourceMgr() const
Definition: Rewriter.h:77
clang::Lexer::MeasureTokenLength
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 ...
Definition: Lexer.cpp:447
clang::Lexer::LexFromRawLexer
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition: Lexer.h:198
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:626
clang::Preprocessor::setPragmasEnabled
void setPragmasEnabled(bool Enabled)
Definition: Preprocessor.h:1007
clang::Preprocessor::getLangOpts
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:960
clang::RewriteBuffer::InsertTextBefore
void InsertTextBefore(unsigned OrigOffset, StringRef Str)
InsertTextBefore - Insert some text before the specified point, where the offset in the buffer is spe...
Definition: RewriteBuffer.h:74
Preprocessor.h
clang::FileID::getHashValue
unsigned getHashValue() const
Definition: SourceLocation.h:57
clang::Lexer
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
Definition: Lexer.h:76
AddLineNumber
static void AddLineNumber(RewriteBuffer &RB, unsigned LineNo, unsigned B, unsigned E)
Definition: HTMLRewrite.cpp:209
clang::Preprocessor::getPragmasEnabled
bool getPragmasEnabled() const
Definition: Preprocessor.h:1008
clang::Preprocessor::SetCommentRetentionState
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments)
Control whether the preprocessor retains comments in output.
Definition: Preprocessor.h:1000
clang::Token::getKind
tok::TokenKind getKind() const
Definition: Token.h:92
clang::html::AddLineNumbers
void AddLineNumbers(Rewriter &R, FileID FID)
Definition: HTMLRewrite.cpp:227
clang::Token::is
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)) {....
Definition: Token.h:97
clang::DiagnosticsEngine::getDiagnosticIDs
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
Definition: Diagnostic.h:550
llvm::SmallString
Definition: LLVM.h:37
clang::Token::isNot
bool isNot(tok::TokenKind K) const
Definition: Token.h:98
clang::html::SyntaxHighlight
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords,...
Definition: HTMLRewrite.cpp:305
clang::Token::getLength
unsigned getLength() const
Definition: Token.h:129
clang::SourceManager::getLocForStartOfFile
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
Definition: SourceManager.h:1118
clang::Preprocessor::getSourceManager
SourceManager & getSourceManager() const
Definition: Preprocessor.h:964
clang::Preprocessor::getSpelling
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
Definition: Preprocessor.h:1759
HTMLRewrite.h
clang::CharSourceRange::isTokenRange
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
Definition: SourceLocation.h:282
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:255
clang::html::EscapeText
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 ...
Definition: HTMLRewrite.cpp:107
clang::Rewriter::getLangOpts
const LangOptions & getLangOpts() const
Definition: Rewriter.h:78
clang::CharSourceRange::getEnd
SourceLocation getEnd() const
Definition: SourceLocation.h:286
clang::Token::getLocation
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:126
clang::SourceLocation::isMacroID
bool isMacroID() const
Definition: SourceLocation.h:105
clang::Rewriter::InsertTextAfter
bool InsertTextAfter(SourceLocation Loc, StringRef Str)
InsertTextAfter - Insert the specified string at the specified location in the original buffer.
Definition: Rewriter.h:123
clang::html::HighlightRange
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.
Definition: HTMLRewrite.cpp:31
clang::Lexer::getBuffer
StringRef getBuffer() const
Gets source code buffer.
Definition: Lexer.h:246
clang
Definition: CalledOnceCheck.h:17
clang::RewriteBuffer
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Definition: RewriteBuffer.h:25
clang::Preprocessor::LookUpIdentifierInfo
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
Definition: Preprocessor.cpp:696
clang::Rewriter::InsertTextBefore
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
InsertText - Insert the specified string at the specified location in the original buffer.
Definition: Rewriter.h:136
clang::Preprocessor::getDiagnostics
DiagnosticsEngine & getDiagnostics() const
Definition: Preprocessor.h:957
clang::FileID
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Definition: SourceLocation.h:40
clang::Preprocessor::setDiagnostics
void setDiagnostics(DiagnosticsEngine &D)
Definition: Preprocessor.h:958
clang::Rewriter
Rewriter - This is the main interface to the rewrite buffers.
Definition: Rewriter.h:32
s
__device__ __2f16 float bool s
Definition: __clang_hip_libdevice_declares.h:315
clang::html::AddHeaderFooterInternalBuiltinCSS
void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, StringRef title)
Definition: HTMLRewrite.cpp:274
clang::Token::setKind
void setKind(tok::TokenKind K)
Definition: Token.h:93
clang::IgnoringDiagConsumer
A diagnostic client that ignores all diagnostics.
Definition: Diagnostic.h:1777
c
__device__ __2f16 float c
Definition: __clang_hip_libdevice_declares.h:315
clang::comments::tok::eof
@ eof
Definition: CommentLexer.h:33
Rewriter.h
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:130
SM
#define SM(sm)
Definition: Cuda.cpp:78
clang::SourceManager::getBufferOrFake
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
Definition: SourceManager.h:1023