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