clang  9.0.0svn
CommentParser.cpp
Go to the documentation of this file.
1 //===--- CommentParser.cpp - Doxygen comment parser -----------------------===//
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 
12 #include "clang/AST/CommentSema.h"
13 #include "clang/Basic/CharInfo.h"
15 #include "llvm/Support/ErrorHandling.h"
16 
17 namespace clang {
18 
19 static inline bool isWhitespace(llvm::StringRef S) {
20  for (StringRef::const_iterator I = S.begin(), E = S.end(); I != E; ++I) {
21  if (!isWhitespace(*I))
22  return false;
23  }
24  return true;
25 }
26 
27 namespace comments {
28 
29 /// Re-lexes a sequence of tok::text tokens.
31  llvm::BumpPtrAllocator &Allocator;
32  Parser &P;
33 
34  /// This flag is set when there are no more tokens we can fetch from lexer.
35  bool NoMoreInterestingTokens;
36 
37  /// Token buffer: tokens we have processed and lookahead.
39 
40  /// A position in \c Toks.
41  struct Position {
42  const char *BufferStart;
43  const char *BufferEnd;
44  const char *BufferPtr;
45  SourceLocation BufferStartLoc;
46  unsigned CurToken;
47  };
48 
49  /// Current position in Toks.
50  Position Pos;
51 
52  bool isEnd() const {
53  return Pos.CurToken >= Toks.size();
54  }
55 
56  /// Sets up the buffer pointers to point to current token.
57  void setupBuffer() {
58  assert(!isEnd());
59  const Token &Tok = Toks[Pos.CurToken];
60 
61  Pos.BufferStart = Tok.getText().begin();
62  Pos.BufferEnd = Tok.getText().end();
63  Pos.BufferPtr = Pos.BufferStart;
64  Pos.BufferStartLoc = Tok.getLocation();
65  }
66 
67  SourceLocation getSourceLocation() const {
68  const unsigned CharNo = Pos.BufferPtr - Pos.BufferStart;
69  return Pos.BufferStartLoc.getLocWithOffset(CharNo);
70  }
71 
72  char peek() const {
73  assert(!isEnd());
74  assert(Pos.BufferPtr != Pos.BufferEnd);
75  return *Pos.BufferPtr;
76  }
77 
78  void consumeChar() {
79  assert(!isEnd());
80  assert(Pos.BufferPtr != Pos.BufferEnd);
81  Pos.BufferPtr++;
82  if (Pos.BufferPtr == Pos.BufferEnd) {
83  Pos.CurToken++;
84  if (isEnd() && !addToken())
85  return;
86 
87  assert(!isEnd());
88  setupBuffer();
89  }
90  }
91 
92  /// Add a token.
93  /// Returns true on success, false if there are no interesting tokens to
94  /// fetch from lexer.
95  bool addToken() {
96  if (NoMoreInterestingTokens)
97  return false;
98 
99  if (P.Tok.is(tok::newline)) {
100  // If we see a single newline token between text tokens, skip it.
101  Token Newline = P.Tok;
102  P.consumeToken();
103  if (P.Tok.isNot(tok::text)) {
104  P.putBack(Newline);
105  NoMoreInterestingTokens = true;
106  return false;
107  }
108  }
109  if (P.Tok.isNot(tok::text)) {
110  NoMoreInterestingTokens = true;
111  return false;
112  }
113 
114  Toks.push_back(P.Tok);
115  P.consumeToken();
116  if (Toks.size() == 1)
117  setupBuffer();
118  return true;
119  }
120 
121  void consumeWhitespace() {
122  while (!isEnd()) {
123  if (isWhitespace(peek()))
124  consumeChar();
125  else
126  break;
127  }
128  }
129 
130  void formTokenWithChars(Token &Result,
131  SourceLocation Loc,
132  const char *TokBegin,
133  unsigned TokLength,
134  StringRef Text) {
135  Result.setLocation(Loc);
136  Result.setKind(tok::text);
137  Result.setLength(TokLength);
138 #ifndef NDEBUG
139  Result.TextPtr = "<UNSET>";
140  Result.IntVal = 7;
141 #endif
142  Result.setText(Text);
143  }
144 
145 public:
146  TextTokenRetokenizer(llvm::BumpPtrAllocator &Allocator, Parser &P):
147  Allocator(Allocator), P(P), NoMoreInterestingTokens(false) {
148  Pos.CurToken = 0;
149  addToken();
150  }
151 
152  /// Extract a word -- sequence of non-whitespace characters.
153  bool lexWord(Token &Tok) {
154  if (isEnd())
155  return false;
156 
157  Position SavedPos = Pos;
158 
159  consumeWhitespace();
160  SmallString<32> WordText;
161  const char *WordBegin = Pos.BufferPtr;
162  SourceLocation Loc = getSourceLocation();
163  while (!isEnd()) {
164  const char C = peek();
165  if (!isWhitespace(C)) {
166  WordText.push_back(C);
167  consumeChar();
168  } else
169  break;
170  }
171  const unsigned Length = WordText.size();
172  if (Length == 0) {
173  Pos = SavedPos;
174  return false;
175  }
176 
177  char *TextPtr = Allocator.Allocate<char>(Length + 1);
178 
179  memcpy(TextPtr, WordText.c_str(), Length + 1);
180  StringRef Text = StringRef(TextPtr, Length);
181 
182  formTokenWithChars(Tok, Loc, WordBegin, Length, Text);
183  return true;
184  }
185 
186  bool lexDelimitedSeq(Token &Tok, char OpenDelim, char CloseDelim) {
187  if (isEnd())
188  return false;
189 
190  Position SavedPos = Pos;
191 
192  consumeWhitespace();
193  SmallString<32> WordText;
194  const char *WordBegin = Pos.BufferPtr;
195  SourceLocation Loc = getSourceLocation();
196  bool Error = false;
197  if (!isEnd()) {
198  const char C = peek();
199  if (C == OpenDelim) {
200  WordText.push_back(C);
201  consumeChar();
202  } else
203  Error = true;
204  }
205  char C = '\0';
206  while (!Error && !isEnd()) {
207  C = peek();
208  WordText.push_back(C);
209  consumeChar();
210  if (C == CloseDelim)
211  break;
212  }
213  if (!Error && C != CloseDelim)
214  Error = true;
215 
216  if (Error) {
217  Pos = SavedPos;
218  return false;
219  }
220 
221  const unsigned Length = WordText.size();
222  char *TextPtr = Allocator.Allocate<char>(Length + 1);
223 
224  memcpy(TextPtr, WordText.c_str(), Length + 1);
225  StringRef Text = StringRef(TextPtr, Length);
226 
227  formTokenWithChars(Tok, Loc, WordBegin,
228  Pos.BufferPtr - WordBegin, Text);
229  return true;
230  }
231 
232  /// Put back tokens that we didn't consume.
234  if (isEnd())
235  return;
236 
237  bool HavePartialTok = false;
238  Token PartialTok;
239  if (Pos.BufferPtr != Pos.BufferStart) {
240  formTokenWithChars(PartialTok, getSourceLocation(),
241  Pos.BufferPtr, Pos.BufferEnd - Pos.BufferPtr,
242  StringRef(Pos.BufferPtr,
243  Pos.BufferEnd - Pos.BufferPtr));
244  HavePartialTok = true;
245  Pos.CurToken++;
246  }
247 
248  P.putBack(llvm::makeArrayRef(Toks.begin() + Pos.CurToken, Toks.end()));
249  Pos.CurToken = Toks.size();
250 
251  if (HavePartialTok)
252  P.putBack(PartialTok);
253  }
254 };
255 
256 Parser::Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
257  const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
258  const CommandTraits &Traits):
259  L(L), S(S), Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),
260  Traits(Traits) {
261  consumeToken();
262 }
263 
265  TextTokenRetokenizer &Retokenizer) {
266  Token Arg;
267  // Check if argument looks like direction specification: [dir]
268  // e.g., [in], [out], [in,out]
269  if (Retokenizer.lexDelimitedSeq(Arg, '[', ']'))
271  Arg.getLocation(),
272  Arg.getEndLocation(),
273  Arg.getText());
274 
275  if (Retokenizer.lexWord(Arg))
277  Arg.getLocation(),
278  Arg.getEndLocation(),
279  Arg.getText());
280 }
281 
283  TextTokenRetokenizer &Retokenizer) {
284  Token Arg;
285  if (Retokenizer.lexWord(Arg))
287  Arg.getLocation(),
288  Arg.getEndLocation(),
289  Arg.getText());
290 }
291 
293  TextTokenRetokenizer &Retokenizer,
294  unsigned NumArgs) {
295  typedef BlockCommandComment::Argument Argument;
296  Argument *Args =
297  new (Allocator.Allocate<Argument>(NumArgs)) Argument[NumArgs];
298  unsigned ParsedArgs = 0;
299  Token Arg;
300  while (ParsedArgs < NumArgs && Retokenizer.lexWord(Arg)) {
301  Args[ParsedArgs] = Argument(SourceRange(Arg.getLocation(),
302  Arg.getEndLocation()),
303  Arg.getText());
304  ParsedArgs++;
305  }
306 
307  S.actOnBlockCommandArgs(BC, llvm::makeArrayRef(Args, ParsedArgs));
308 }
309 
311  assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
312 
313  ParamCommandComment *PC = nullptr;
314  TParamCommandComment *TPC = nullptr;
315  BlockCommandComment *BC = nullptr;
316  const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
317  CommandMarkerKind CommandMarker =
319  if (Info->IsParamCommand) {
320  PC = S.actOnParamCommandStart(Tok.getLocation(),
321  Tok.getEndLocation(),
322  Tok.getCommandID(),
323  CommandMarker);
324  } else if (Info->IsTParamCommand) {
325  TPC = S.actOnTParamCommandStart(Tok.getLocation(),
326  Tok.getEndLocation(),
327  Tok.getCommandID(),
328  CommandMarker);
329  } else {
330  BC = S.actOnBlockCommandStart(Tok.getLocation(),
331  Tok.getEndLocation(),
332  Tok.getCommandID(),
333  CommandMarker);
334  }
335  consumeToken();
336 
337  if (isTokBlockCommand()) {
338  // Block command ahead. We can't nest block commands, so pretend that this
339  // command has an empty argument.
340  ParagraphComment *Paragraph = S.actOnParagraphComment(None);
341  if (PC) {
342  S.actOnParamCommandFinish(PC, Paragraph);
343  return PC;
344  } else if (TPC) {
345  S.actOnTParamCommandFinish(TPC, Paragraph);
346  return TPC;
347  } else {
348  S.actOnBlockCommandFinish(BC, Paragraph);
349  return BC;
350  }
351  }
352 
353  if (PC || TPC || Info->NumArgs > 0) {
354  // In order to parse command arguments we need to retokenize a few
355  // following text tokens.
356  TextTokenRetokenizer Retokenizer(Allocator, *this);
357 
358  if (PC)
359  parseParamCommandArgs(PC, Retokenizer);
360  else if (TPC)
361  parseTParamCommandArgs(TPC, Retokenizer);
362  else
363  parseBlockCommandArgs(BC, Retokenizer, Info->NumArgs);
364 
365  Retokenizer.putBackLeftoverTokens();
366  }
367 
368  // If there's a block command ahead, we will attach an empty paragraph to
369  // this command.
370  bool EmptyParagraph = false;
371  if (isTokBlockCommand())
372  EmptyParagraph = true;
373  else if (Tok.is(tok::newline)) {
374  Token PrevTok = Tok;
375  consumeToken();
376  EmptyParagraph = isTokBlockCommand();
377  putBack(PrevTok);
378  }
379 
380  ParagraphComment *Paragraph;
381  if (EmptyParagraph)
382  Paragraph = S.actOnParagraphComment(None);
383  else {
385  // Since we have checked for a block command, we should have parsed a
386  // paragraph.
387  Paragraph = cast<ParagraphComment>(Block);
388  }
389 
390  if (PC) {
391  S.actOnParamCommandFinish(PC, Paragraph);
392  return PC;
393  } else if (TPC) {
394  S.actOnTParamCommandFinish(TPC, Paragraph);
395  return TPC;
396  } else {
397  S.actOnBlockCommandFinish(BC, Paragraph);
398  return BC;
399  }
400 }
401 
403  assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
404 
405  const Token CommandTok = Tok;
406  consumeToken();
407 
408  TextTokenRetokenizer Retokenizer(Allocator, *this);
409 
410  Token ArgTok;
411  bool ArgTokValid = Retokenizer.lexWord(ArgTok);
412 
414  if (ArgTokValid) {
415  IC = S.actOnInlineCommand(CommandTok.getLocation(),
416  CommandTok.getEndLocation(),
417  CommandTok.getCommandID(),
418  ArgTok.getLocation(),
419  ArgTok.getEndLocation(),
420  ArgTok.getText());
421  } else {
422  IC = S.actOnInlineCommand(CommandTok.getLocation(),
423  CommandTok.getEndLocation(),
424  CommandTok.getCommandID());
425  }
426 
427  Retokenizer.putBackLeftoverTokens();
428 
429  return IC;
430 }
431 
433  assert(Tok.is(tok::html_start_tag));
434  HTMLStartTagComment *HST =
436  Tok.getHTMLTagStartName());
437  consumeToken();
438 
440  while (true) {
441  switch (Tok.getKind()) {
442  case tok::html_ident: {
443  Token Ident = Tok;
444  consumeToken();
445  if (Tok.isNot(tok::html_equals)) {
446  Attrs.push_back(HTMLStartTagComment::Attribute(Ident.getLocation(),
447  Ident.getHTMLIdent()));
448  continue;
449  }
450  Token Equals = Tok;
451  consumeToken();
452  if (Tok.isNot(tok::html_quoted_string)) {
453  Diag(Tok.getLocation(),
454  diag::warn_doc_html_start_tag_expected_quoted_string)
455  << SourceRange(Equals.getLocation());
456  Attrs.push_back(HTMLStartTagComment::Attribute(Ident.getLocation(),
457  Ident.getHTMLIdent()));
458  while (Tok.is(tok::html_equals) ||
460  consumeToken();
461  continue;
462  }
463  Attrs.push_back(HTMLStartTagComment::Attribute(
464  Ident.getLocation(),
465  Ident.getHTMLIdent(),
466  Equals.getLocation(),
467  SourceRange(Tok.getLocation(),
468  Tok.getEndLocation()),
469  Tok.getHTMLQuotedString()));
470  consumeToken();
471  continue;
472  }
473 
474  case tok::html_greater:
476  S.copyArray(llvm::makeArrayRef(Attrs)),
477  Tok.getLocation(),
478  /* IsSelfClosing = */ false);
479  consumeToken();
480  return HST;
481 
484  S.copyArray(llvm::makeArrayRef(Attrs)),
485  Tok.getLocation(),
486  /* IsSelfClosing = */ true);
487  consumeToken();
488  return HST;
489 
490  case tok::html_equals:
492  Diag(Tok.getLocation(),
493  diag::warn_doc_html_start_tag_expected_ident_or_greater);
494  while (Tok.is(tok::html_equals) ||
496  consumeToken();
497  if (Tok.is(tok::html_ident) ||
498  Tok.is(tok::html_greater) ||
500  continue;
501 
503  S.copyArray(llvm::makeArrayRef(Attrs)),
504  SourceLocation(),
505  /* IsSelfClosing = */ false);
506  return HST;
507 
508  default:
509  // Not a token from an HTML start tag. Thus HTML tag prematurely ended.
511  S.copyArray(llvm::makeArrayRef(Attrs)),
512  SourceLocation(),
513  /* IsSelfClosing = */ false);
514  bool StartLineInvalid;
515  const unsigned StartLine = SourceMgr.getPresumedLineNumber(
516  HST->getLocation(),
517  &StartLineInvalid);
518  bool EndLineInvalid;
519  const unsigned EndLine = SourceMgr.getPresumedLineNumber(
520  Tok.getLocation(),
521  &EndLineInvalid);
522  if (StartLineInvalid || EndLineInvalid || StartLine == EndLine)
523  Diag(Tok.getLocation(),
524  diag::warn_doc_html_start_tag_expected_ident_or_greater)
525  << HST->getSourceRange();
526  else {
527  Diag(Tok.getLocation(),
528  diag::warn_doc_html_start_tag_expected_ident_or_greater);
529  Diag(HST->getLocation(), diag::note_doc_html_tag_started_here)
530  << HST->getSourceRange();
531  }
532  return HST;
533  }
534  }
535 }
536 
538  assert(Tok.is(tok::html_end_tag));
539  Token TokEndTag = Tok;
540  consumeToken();
541  SourceLocation Loc;
542  if (Tok.is(tok::html_greater)) {
543  Loc = Tok.getLocation();
544  consumeToken();
545  }
546 
547  return S.actOnHTMLEndTag(TokEndTag.getLocation(),
548  Loc,
549  TokEndTag.getHTMLTagEndName());
550 }
551 
554 
555  while (true) {
556  switch (Tok.getKind()) {
559  case tok::eof:
560  break; // Block content or EOF ahead, finish this parapgaph.
561 
563  Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
564  Tok.getEndLocation(),
565  Tok.getUnknownCommandName()));
566  consumeToken();
567  continue;
568 
570  case tok::at_command: {
571  const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
572  if (Info->IsBlockCommand) {
573  if (Content.size() == 0)
574  return parseBlockCommand();
575  break; // Block command ahead, finish this parapgaph.
576  }
577  if (Info->IsVerbatimBlockEndCommand) {
578  Diag(Tok.getLocation(),
579  diag::warn_verbatim_block_end_without_start)
580  << Tok.is(tok::at_command)
581  << Info->Name
582  << SourceRange(Tok.getLocation(), Tok.getEndLocation());
583  consumeToken();
584  continue;
585  }
586  if (Info->IsUnknownCommand) {
587  Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
588  Tok.getEndLocation(),
589  Info->getID()));
590  consumeToken();
591  continue;
592  }
593  assert(Info->IsInlineCommand);
594  Content.push_back(parseInlineCommand());
595  continue;
596  }
597 
598  case tok::newline: {
599  consumeToken();
600  if (Tok.is(tok::newline) || Tok.is(tok::eof)) {
601  consumeToken();
602  break; // Two newlines -- end of paragraph.
603  }
604  // Also allow [tok::newline, tok::text, tok::newline] if the middle
605  // tok::text is just whitespace.
606  if (Tok.is(tok::text) && isWhitespace(Tok.getText())) {
607  Token WhitespaceTok = Tok;
608  consumeToken();
609  if (Tok.is(tok::newline) || Tok.is(tok::eof)) {
610  consumeToken();
611  break;
612  }
613  // We have [tok::newline, tok::text, non-newline]. Put back tok::text.
614  putBack(WhitespaceTok);
615  }
616  if (Content.size() > 0)
617  Content.back()->addTrailingNewline();
618  continue;
619  }
620 
621  // Don't deal with HTML tag soup now.
622  case tok::html_start_tag:
623  Content.push_back(parseHTMLStartTag());
624  continue;
625 
626  case tok::html_end_tag:
627  Content.push_back(parseHTMLEndTag());
628  continue;
629 
630  case tok::text:
631  Content.push_back(S.actOnText(Tok.getLocation(),
632  Tok.getEndLocation(),
633  Tok.getText()));
634  consumeToken();
635  continue;
636 
640  case tok::html_ident:
641  case tok::html_equals:
643  case tok::html_greater:
645  llvm_unreachable("should not see this token");
646  }
647  break;
648  }
649 
650  return S.actOnParagraphComment(S.copyArray(llvm::makeArrayRef(Content)));
651 }
652 
654  assert(Tok.is(tok::verbatim_block_begin));
655 
658  Tok.getVerbatimBlockID());
659  consumeToken();
660 
661  // Don't create an empty line if verbatim opening command is followed
662  // by a newline.
663  if (Tok.is(tok::newline))
664  consumeToken();
665 
667  while (Tok.is(tok::verbatim_block_line) ||
668  Tok.is(tok::newline)) {
670  if (Tok.is(tok::verbatim_block_line)) {
671  Line = S.actOnVerbatimBlockLine(Tok.getLocation(),
672  Tok.getVerbatimBlockText());
673  consumeToken();
674  if (Tok.is(tok::newline)) {
675  consumeToken();
676  }
677  } else {
678  // Empty line, just a tok::newline.
679  Line = S.actOnVerbatimBlockLine(Tok.getLocation(), "");
680  consumeToken();
681  }
682  Lines.push_back(Line);
683  }
684 
685  if (Tok.is(tok::verbatim_block_end)) {
686  const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID());
688  Info->Name,
689  S.copyArray(llvm::makeArrayRef(Lines)));
690  consumeToken();
691  } else {
692  // Unterminated \\verbatim block
694  S.copyArray(llvm::makeArrayRef(Lines)));
695  }
696 
697  return VB;
698 }
699 
701  assert(Tok.is(tok::verbatim_line_name));
702 
703  Token NameTok = Tok;
704  consumeToken();
705 
706  SourceLocation TextBegin;
707  StringRef Text;
708  // Next token might not be a tok::verbatim_line_text if verbatim line
709  // starting command comes just before a newline or comment end.
710  if (Tok.is(tok::verbatim_line_text)) {
711  TextBegin = Tok.getLocation();
712  Text = Tok.getVerbatimLineText();
713  } else {
714  TextBegin = NameTok.getEndLocation();
715  Text = "";
716  }
717 
718  VerbatimLineComment *VL = S.actOnVerbatimLine(NameTok.getLocation(),
719  NameTok.getVerbatimLineID(),
720  TextBegin,
721  Text);
722  consumeToken();
723  return VL;
724 }
725 
727  switch (Tok.getKind()) {
728  case tok::text:
731  case tok::at_command:
732  case tok::html_start_tag:
733  case tok::html_end_tag:
735 
737  return parseVerbatimBlock();
738 
740  return parseVerbatimLine();
741 
742  case tok::eof:
743  case tok::newline:
747  case tok::html_ident:
748  case tok::html_equals:
750  case tok::html_greater:
752  llvm_unreachable("should not see this token");
753  }
754  llvm_unreachable("bogus token kind");
755 }
756 
758  // Skip newlines at the beginning of the comment.
759  while (Tok.is(tok::newline))
760  consumeToken();
761 
763  while (Tok.isNot(tok::eof)) {
764  Blocks.push_back(parseBlockContent());
765 
766  // Skip extra newlines after paragraph end.
767  while (Tok.is(tok::newline))
768  consumeToken();
769  }
770  return S.actOnFullComment(S.copyArray(llvm::makeArrayRef(Blocks)));
771 }
772 
773 } // end namespace comments
774 } // end namespace clang
void actOnParamCommandFinish(ParamCommandComment *Command, ParagraphComment *Paragraph)
SourceLocation getEndLocation() const LLVM_READONLY
Definition: CommentLexer.h:83
void putBackLeftoverTokens()
Put back tokens that we didn&#39;t consume.
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, ArrayRef< HTMLStartTagComment::Attribute > Attrs, SourceLocation GreaterLoc, bool IsSelfClosing)
Defines the SourceManager interface.
VerbatimLineComment * parseVerbatimLine()
ParagraphComment * actOnParagraphComment(ArrayRef< InlineContentComment *> Content)
Definition: CommentSema.cpp:44
unsigned getVerbatimBlockID() const LLVM_READONLY
Definition: CommentLexer.h:130
void setLength(unsigned L)
Definition: CommentLexer.h:96
VerbatimBlockComment * actOnVerbatimBlockStart(SourceLocation Loc, unsigned CommandID)
void setText(StringRef Text)
Definition: CommentLexer.h:103
HTMLStartTagComment * actOnHTMLStartTagStart(SourceLocation LocBegin, StringRef TagName)
void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef< BlockCommandComment::Argument > Args)
Definition: CommentSema.cpp:61
Information about a single command.
tok::TokenKind getKind() const LLVM_READONLY
Definition: CommentLexer.h:89
StringRef getVerbatimLineText() const LLVM_READONLY
Definition: CommentLexer.h:161
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, SourceLocation CloseNameLocBegin, StringRef CloseName, ArrayRef< VerbatimBlockLineComment *> Lines)
bool isNot(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:93
TextComment * actOnText(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text)
A command with word-like arguments that is considered inline content.
Definition: Comment.h:298
InlineCommandComment * parseInlineCommand()
A line of text contained in a verbatim block.
Definition: Comment.h:863
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: &#39; &#39;, &#39;\t&#39;, &#39;\f&#39;, &#39;\v&#39;, &#39;\n&#39;, &#39;\r&#39;.
Definition: CharInfo.h:87
A verbatim line command.
Definition: Comment.h:943
const FormatToken & Tok
StringRef getHTMLTagStartName() const LLVM_READONLY
Definition: CommentLexer.h:172
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
InlineContentComment * actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, StringRef CommandName)
void parseParamCommandArgs(ParamCommandComment *PC, TextTokenRetokenizer &Retokenizer)
Parse arguments for \param command.
FullComment * actOnFullComment(ArrayRef< BlockContentComment *> Blocks)
void setLocation(SourceLocation SL)
Definition: CommentLexer.h:81
ArrayRef< T > copyArray(ArrayRef< T > Source)
Returns a copy of array, owned by Sema&#39;s allocator.
Definition: CommentSema.h:80
A verbatim block command (e.
Definition: Comment.h:891
unsigned IsParamCommand
True if this command is introducing documentation for a function parameter (\param or an alias)...
BlockContentComment * parseParagraphOrBlockCommand()
void actOnTParamCommandFinish(TParamCommandComment *Command, ParagraphComment *Paragraph)
const AnnotatedLine * Line
Command started with an &#39;at&#39; character:
Definition: Comment.h:47
CommandMarkerKind
Describes the syntax that was used in a documentation command.
Definition: Comment.h:36
A command that has zero or more word-like arguments (number of word-like arguments depends on command...
Definition: Comment.h:596
void parseTParamCommandArgs(TParamCommandComment *TPC, TextTokenRetokenizer &Retokenizer)
Parse arguments for \tparam command.
VerbatimBlockLineComment * actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text)
unsigned IsTParamCommand
True if this command is introducing documentation for a template parameter (\tparam or an alias)...
An opening HTML tag with attributes.
Definition: Comment.h:413
SourceLocation getLocation() const LLVM_READONLY
Definition: CommentLexer.h:80
StringRef getHTMLQuotedString() const LLVM_READONLY
Definition: CommentLexer.h:194
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool is(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:92
TParamCommandComment * actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
void actOnBlockCommandFinish(BlockCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:66
This class provides information about commands that can be used in comments.
#define false
Definition: stdbool.h:17
Re-lexes a sequence of tok::text tokens.
Encodes a location in the source.
VerbatimLineComment * actOnVerbatimLine(SourceLocation LocBegin, unsigned CommandID, SourceLocation TextBegin, StringRef Text)
ParamCommandComment * actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:79
Comment lexer.
Definition: CommentLexer.h:220
const CommandInfo * getCommandInfo(StringRef Name) const
Block content (contains inline content).
Definition: Comment.h:530
HTMLEndTagComment * parseHTMLEndTag()
FullComment * parseFullComment()
A closing HTML tag.
Definition: Comment.h:507
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Doxygen \tparam command, describes a template parameter.
Definition: Comment.h:799
BlockCommandComment * parseBlockCommand()
Dataflow Directional Tag Classes.
BlockCommandComment * actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:49
Command started with a backslash character:
Definition: Comment.h:41
void setKind(tok::TokenKind K)
Definition: CommentLexer.h:90
TextTokenRetokenizer(llvm::BumpPtrAllocator &Allocator, Parser &P)
BlockContentComment * parseBlockContent()
A single paragraph that contains inline content.
Definition: Comment.h:546
unsigned IsVerbatimBlockEndCommand
True if this command is an end command for a verbatim-like block.
HTMLEndTagComment * actOnHTMLEndTag(SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName)
unsigned getCommandID() const LLVM_READONLY
Definition: CommentLexer.h:120
HTMLStartTagComment * parseHTMLStartTag()
StringRef getUnknownCommandName() const LLVM_READONLY
Definition: CommentLexer.h:109
unsigned IsUnknownCommand
True if this command is unknown.
VerbatimBlockComment * parseVerbatimBlock()
Comment token.
Definition: CommentLexer.h:55
unsigned IsBlockCommand
True if this command is a block command (of any kind).
Doxygen comment parser.
Definition: CommentParser.h:29
void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
StringRef getVerbatimBlockText() const LLVM_READONLY
Definition: CommentLexer.h:140
void parseBlockCommandArgs(BlockCommandComment *BC, TextTokenRetokenizer &Retokenizer, unsigned NumArgs)
bool lexWord(Token &Tok)
Extract a word – sequence of non-whitespace characters.
unsigned IsInlineCommand
True if this command is a inline command (of any kind).
InlineCommandComment * actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, unsigned CommandID)
StringRef getText() const LLVM_READONLY
Definition: CommentLexer.h:98
Doxygen \param command.
Definition: Comment.h:711
bool lexDelimitedSeq(Token &Tok, char OpenDelim, char CloseDelim)
unsigned NumArgs
Number of word-like arguments for a given block command, except for \param and \tparam commands – th...
StringRef Text
Definition: Format.cpp:1712
A trivial tuple used to represent a source range.
void actOnParamCommandParamNameArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
This class handles loading and caching of source files into memory.
void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
A full comment attached to a declaration, contains block content.
Definition: Comment.h:1091
StringRef getHTMLIdent() const LLVM_READONLY
Definition: CommentLexer.h:183