clang 19.0.0git
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
15#include "llvm/Support/ErrorHandling.h"
16
17namespace clang {
18
19static 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
27namespace 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
145public:
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::ArrayRef(Toks.begin() + Pos.CurToken, Toks.end()));
249 Pos.CurToken = Toks.size();
250
251 if (HavePartialTok)
252 P.putBack(PartialTok);
253 }
254};
255
256Parser::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
293Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) {
294 auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))
295 Comment::Argument[NumArgs];
296 unsigned ParsedArgs = 0;
297 Token Arg;
298 while (ParsedArgs < NumArgs && Retokenizer.lexWord(Arg)) {
299 Args[ParsedArgs] = Comment::Argument{
300 SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
301 ParsedArgs++;
302 }
303
304 return llvm::ArrayRef(Args, ParsedArgs);
305}
306
308 assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
309
310 ParamCommandComment *PC = nullptr;
311 TParamCommandComment *TPC = nullptr;
312 BlockCommandComment *BC = nullptr;
313 const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
314 CommandMarkerKind CommandMarker =
316 if (Info->IsParamCommand) {
318 Tok.getEndLocation(),
319 Tok.getCommandID(),
320 CommandMarker);
321 } else if (Info->IsTParamCommand) {
323 Tok.getEndLocation(),
324 Tok.getCommandID(),
325 CommandMarker);
326 } else {
328 Tok.getEndLocation(),
329 Tok.getCommandID(),
330 CommandMarker);
331 }
332 consumeToken();
333
334 if (isTokBlockCommand()) {
335 // Block command ahead. We can't nest block commands, so pretend that this
336 // command has an empty argument.
337 ParagraphComment *Paragraph = S.actOnParagraphComment(std::nullopt);
338 if (PC) {
339 S.actOnParamCommandFinish(PC, Paragraph);
340 return PC;
341 } else if (TPC) {
342 S.actOnTParamCommandFinish(TPC, Paragraph);
343 return TPC;
344 } else {
345 S.actOnBlockCommandFinish(BC, Paragraph);
346 return BC;
347 }
348 }
349
350 if (PC || TPC || Info->NumArgs > 0) {
351 // In order to parse command arguments we need to retokenize a few
352 // following text tokens.
353 TextTokenRetokenizer Retokenizer(Allocator, *this);
354
355 if (PC)
356 parseParamCommandArgs(PC, Retokenizer);
357 else if (TPC)
358 parseTParamCommandArgs(TPC, Retokenizer);
359 else
360 S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs));
361
362 Retokenizer.putBackLeftoverTokens();
363 }
364
365 // If there's a block command ahead, we will attach an empty paragraph to
366 // this command.
367 bool EmptyParagraph = false;
368 if (isTokBlockCommand())
369 EmptyParagraph = true;
370 else if (Tok.is(tok::newline)) {
371 Token PrevTok = Tok;
372 consumeToken();
373 EmptyParagraph = isTokBlockCommand();
374 putBack(PrevTok);
375 }
376
377 ParagraphComment *Paragraph;
378 if (EmptyParagraph)
379 Paragraph = S.actOnParagraphComment(std::nullopt);
380 else {
382 // Since we have checked for a block command, we should have parsed a
383 // paragraph.
384 Paragraph = cast<ParagraphComment>(Block);
385 }
386
387 if (PC) {
388 S.actOnParamCommandFinish(PC, Paragraph);
389 return PC;
390 } else if (TPC) {
391 S.actOnTParamCommandFinish(TPC, Paragraph);
392 return TPC;
393 } else {
394 S.actOnBlockCommandFinish(BC, Paragraph);
395 return BC;
396 }
397}
398
400 assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));
401 const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
402
403 const Token CommandTok = Tok;
404 consumeToken();
405
406 TextTokenRetokenizer Retokenizer(Allocator, *this);
408 parseCommandArgs(Retokenizer, Info->NumArgs);
409
411 CommandTok.getLocation(), CommandTok.getEndLocation(),
412 CommandTok.getCommandID(), Args);
413
414 if (Args.size() < Info->NumArgs) {
415 Diag(CommandTok.getEndLocation().getLocWithOffset(1),
416 diag::warn_doc_inline_command_not_enough_arguments)
417 << CommandTok.is(tok::at_command) << Info->Name << Args.size()
418 << Info->NumArgs
419 << SourceRange(CommandTok.getLocation(), CommandTok.getEndLocation());
420 }
421
422 Retokenizer.putBackLeftoverTokens();
423
424 return IC;
425}
426
428 assert(Tok.is(tok::html_start_tag));
431 Tok.getHTMLTagStartName());
432 consumeToken();
433
435 while (true) {
436 switch (Tok.getKind()) {
437 case tok::html_ident: {
438 Token Ident = Tok;
439 consumeToken();
440 if (Tok.isNot(tok::html_equals)) {
441 Attrs.push_back(HTMLStartTagComment::Attribute(Ident.getLocation(),
442 Ident.getHTMLIdent()));
443 continue;
444 }
445 Token Equals = Tok;
446 consumeToken();
448 Diag(Tok.getLocation(),
449 diag::warn_doc_html_start_tag_expected_quoted_string)
450 << SourceRange(Equals.getLocation());
451 Attrs.push_back(HTMLStartTagComment::Attribute(Ident.getLocation(),
452 Ident.getHTMLIdent()));
453 while (Tok.is(tok::html_equals) ||
455 consumeToken();
456 continue;
457 }
458 Attrs.push_back(HTMLStartTagComment::Attribute(
459 Ident.getLocation(),
460 Ident.getHTMLIdent(),
461 Equals.getLocation(),
463 Tok.getEndLocation()),
464 Tok.getHTMLQuotedString()));
465 consumeToken();
466 continue;
467 }
468
471 Tok.getLocation(),
472 /* IsSelfClosing = */ false);
473 consumeToken();
474 return HST;
475
478 Tok.getLocation(),
479 /* IsSelfClosing = */ true);
480 consumeToken();
481 return HST;
482
483 case tok::html_equals:
485 Diag(Tok.getLocation(),
486 diag::warn_doc_html_start_tag_expected_ident_or_greater);
487 while (Tok.is(tok::html_equals) ||
489 consumeToken();
490 if (Tok.is(tok::html_ident) ||
491 Tok.is(tok::html_greater) ||
493 continue;
494
497 /* IsSelfClosing = */ false);
498 return HST;
499
500 default:
501 // Not a token from an HTML start tag. Thus HTML tag prematurely ended.
504 /* IsSelfClosing = */ false);
505 bool StartLineInvalid;
506 const unsigned StartLine = SourceMgr.getPresumedLineNumber(
507 HST->getLocation(),
508 &StartLineInvalid);
509 bool EndLineInvalid;
510 const unsigned EndLine = SourceMgr.getPresumedLineNumber(
511 Tok.getLocation(),
512 &EndLineInvalid);
513 if (StartLineInvalid || EndLineInvalid || StartLine == EndLine)
514 Diag(Tok.getLocation(),
515 diag::warn_doc_html_start_tag_expected_ident_or_greater)
516 << HST->getSourceRange();
517 else {
518 Diag(Tok.getLocation(),
519 diag::warn_doc_html_start_tag_expected_ident_or_greater);
520 Diag(HST->getLocation(), diag::note_doc_html_tag_started_here)
521 << HST->getSourceRange();
522 }
523 return HST;
524 }
525 }
526}
527
529 assert(Tok.is(tok::html_end_tag));
530 Token TokEndTag = Tok;
531 consumeToken();
532 SourceLocation Loc;
533 if (Tok.is(tok::html_greater)) {
534 Loc = Tok.getLocation();
535 consumeToken();
536 }
537
538 return S.actOnHTMLEndTag(TokEndTag.getLocation(),
539 Loc,
540 TokEndTag.getHTMLTagEndName());
541}
542
545
546 while (true) {
547 switch (Tok.getKind()) {
550 case tok::eof:
551 break; // Block content or EOF ahead, finish this parapgaph.
552
554 Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
555 Tok.getEndLocation(),
556 Tok.getUnknownCommandName()));
557 consumeToken();
558 continue;
559
561 case tok::at_command: {
562 const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
563 if (Info->IsBlockCommand) {
564 if (Content.size() == 0)
565 return parseBlockCommand();
566 break; // Block command ahead, finish this parapgaph.
567 }
568 if (Info->IsVerbatimBlockEndCommand) {
569 Diag(Tok.getLocation(),
570 diag::warn_verbatim_block_end_without_start)
571 << Tok.is(tok::at_command)
572 << Info->Name
573 << SourceRange(Tok.getLocation(), Tok.getEndLocation());
574 consumeToken();
575 continue;
576 }
577 if (Info->IsUnknownCommand) {
578 Content.push_back(S.actOnUnknownCommand(Tok.getLocation(),
579 Tok.getEndLocation(),
580 Info->getID()));
581 consumeToken();
582 continue;
583 }
584 assert(Info->IsInlineCommand);
585 Content.push_back(parseInlineCommand());
586 continue;
587 }
588
589 case tok::newline: {
590 consumeToken();
591 if (Tok.is(tok::newline) || Tok.is(tok::eof)) {
592 consumeToken();
593 break; // Two newlines -- end of paragraph.
594 }
595 // Also allow [tok::newline, tok::text, tok::newline] if the middle
596 // tok::text is just whitespace.
597 if (Tok.is(tok::text) && isWhitespace(Tok.getText())) {
598 Token WhitespaceTok = Tok;
599 consumeToken();
600 if (Tok.is(tok::newline) || Tok.is(tok::eof)) {
601 consumeToken();
602 break;
603 }
604 // We have [tok::newline, tok::text, non-newline]. Put back tok::text.
605 putBack(WhitespaceTok);
606 }
607 if (Content.size() > 0)
608 Content.back()->addTrailingNewline();
609 continue;
610 }
611
612 // Don't deal with HTML tag soup now.
614 Content.push_back(parseHTMLStartTag());
615 continue;
616
618 Content.push_back(parseHTMLEndTag());
619 continue;
620
621 case tok::text:
622 Content.push_back(S.actOnText(Tok.getLocation(),
623 Tok.getEndLocation(),
624 Tok.getText()));
625 consumeToken();
626 continue;
627
631 case tok::html_ident:
632 case tok::html_equals:
636 llvm_unreachable("should not see this token");
637 }
638 break;
639 }
640
641 return S.actOnParagraphComment(S.copyArray(llvm::ArrayRef(Content)));
642}
643
645 assert(Tok.is(tok::verbatim_block_begin));
646
649 Tok.getVerbatimBlockID());
650 consumeToken();
651
652 // Don't create an empty line if verbatim opening command is followed
653 // by a newline.
654 if (Tok.is(tok::newline))
655 consumeToken();
656
658 while (Tok.is(tok::verbatim_block_line) ||
659 Tok.is(tok::newline)) {
661 if (Tok.is(tok::verbatim_block_line)) {
664 consumeToken();
665 if (Tok.is(tok::newline)) {
666 consumeToken();
667 }
668 } else {
669 // Empty line, just a tok::newline.
671 consumeToken();
672 }
673 Lines.push_back(Line);
674 }
675
676 if (Tok.is(tok::verbatim_block_end)) {
677 const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID());
678 S.actOnVerbatimBlockFinish(VB, Tok.getLocation(), Info->Name,
679 S.copyArray(llvm::ArrayRef(Lines)));
680 consumeToken();
681 } else {
682 // Unterminated \\verbatim block
684 S.copyArray(llvm::ArrayRef(Lines)));
685 }
686
687 return VB;
688}
689
691 assert(Tok.is(tok::verbatim_line_name));
692
693 Token NameTok = Tok;
694 consumeToken();
695
696 SourceLocation TextBegin;
697 StringRef Text;
698 // Next token might not be a tok::verbatim_line_text if verbatim line
699 // starting command comes just before a newline or comment end.
700 if (Tok.is(tok::verbatim_line_text)) {
701 TextBegin = Tok.getLocation();
703 } else {
704 TextBegin = NameTok.getEndLocation();
705 Text = "";
706 }
707
709 NameTok.getVerbatimLineID(),
710 TextBegin,
711 Text);
712 consumeToken();
713 return VL;
714}
715
717 switch (Tok.getKind()) {
718 case tok::text:
721 case tok::at_command:
725
727 return parseVerbatimBlock();
728
730 return parseVerbatimLine();
731
732 case tok::eof:
733 case tok::newline:
737 case tok::html_ident:
738 case tok::html_equals:
742 llvm_unreachable("should not see this token");
743 }
744 llvm_unreachable("bogus token kind");
745}
746
748 // Skip newlines at the beginning of the comment.
749 while (Tok.is(tok::newline))
750 consumeToken();
751
753 while (Tok.isNot(tok::eof)) {
754 Blocks.push_back(parseBlockContent());
755
756 // Skip extra newlines after paragraph end.
757 while (Tok.is(tok::newline))
758 consumeToken();
759 }
760 return S.actOnFullComment(S.copyArray(llvm::ArrayRef(Blocks)));
761}
762
763} // end namespace comments
764} // end namespace clang
StringRef P
StringRef Text
Definition: Format.cpp:2972
Defines the SourceManager interface.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
A command that has zero or more word-like arguments (number of word-like arguments depends on command...
Definition: Comment.h:604
Block content (contains inline content).
Definition: Comment.h:538
This class provides information about commands that can be used in comments.
const CommandInfo * getCommandInfo(StringRef Name) const
SourceLocation getLocation() const LLVM_READONLY
Definition: Comment.h:249
SourceRange getSourceRange() const LLVM_READONLY
Definition: Comment.h:243
A full comment attached to a declaration, contains block content.
Definition: Comment.h:1083
An opening HTML tag with attributes.
Definition: Comment.h:433
A command with word-like arguments that is considered inline content.
Definition: Comment.h:335
A single paragraph that contains inline content.
Definition: Comment.h:555
Doxygen \param command.
Definition: Comment.h:711
Doxygen comment parser.
Definition: CommentParser.h:29
VerbatimLineComment * parseVerbatimLine()
InlineCommandComment * parseInlineCommand()
ArrayRef< Comment::Argument > parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs)
void parseTParamCommandArgs(TParamCommandComment *TPC, TextTokenRetokenizer &Retokenizer)
Parse arguments for \tparam command.
BlockContentComment * parseParagraphOrBlockCommand()
HTMLEndTagComment * parseHTMLEndTag()
VerbatimBlockComment * parseVerbatimBlock()
BlockCommandComment * parseBlockCommand()
BlockContentComment * parseBlockContent()
HTMLStartTagComment * parseHTMLStartTag()
FullComment * parseFullComment()
void parseParamCommandArgs(ParamCommandComment *PC, TextTokenRetokenizer &Retokenizer)
Parse arguments for \param command.
FullComment * actOnFullComment(ArrayRef< BlockContentComment * > Blocks)
void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
TParamCommandComment * actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
void actOnTParamCommandFinish(TParamCommandComment *Command, ParagraphComment *Paragraph)
void actOnBlockCommandFinish(BlockCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:67
TextComment * actOnText(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text)
void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef< BlockCommandComment::Argument > Args)
Definition: CommentSema.cpp:62
BlockCommandComment * actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:50
void actOnParamCommandParamNameArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
HTMLEndTagComment * actOnHTMLEndTag(SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName)
InlineCommandComment * actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, unsigned CommandID, ArrayRef< Comment::Argument > Args)
VerbatimLineComment * actOnVerbatimLine(SourceLocation LocBegin, unsigned CommandID, SourceLocation TextBegin, StringRef Text)
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, SourceLocation CloseNameLocBegin, StringRef CloseName, ArrayRef< VerbatimBlockLineComment * > Lines)
VerbatimBlockLineComment * actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text)
void actOnParamCommandFinish(ParamCommandComment *Command, ParagraphComment *Paragraph)
ArrayRef< T > copyArray(ArrayRef< T > Source)
Returns a copy of array, owned by Sema's allocator.
Definition: CommentSema.h:80
HTMLStartTagComment * actOnHTMLStartTagStart(SourceLocation LocBegin, StringRef TagName)
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, ArrayRef< HTMLStartTagComment::Attribute > Attrs, SourceLocation GreaterLoc, bool IsSelfClosing)
ParamCommandComment * actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:80
VerbatimBlockComment * actOnVerbatimBlockStart(SourceLocation Loc, unsigned CommandID)
void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
InlineContentComment * actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, StringRef CommandName)
ParagraphComment * actOnParagraphComment(ArrayRef< InlineContentComment * > Content)
Definition: CommentSema.cpp:45
Doxygen \tparam command, describes a template parameter.
Definition: Comment.h:793
Re-lexes a sequence of tok::text tokens.
void putBackLeftoverTokens()
Put back tokens that we didn't consume.
bool lexDelimitedSeq(Token &Tok, char OpenDelim, char CloseDelim)
TextTokenRetokenizer(llvm::BumpPtrAllocator &Allocator, Parser &P)
bool lexWord(Token &Tok)
Extract a word – sequence of non-whitespace characters.
Comment token.
Definition: CommentLexer.h:55
StringRef getHTMLQuotedString() const LLVM_READONLY
Definition: CommentLexer.h:194
bool isNot(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:93
SourceLocation getEndLocation() const LLVM_READONLY
Definition: CommentLexer.h:83
unsigned getCommandID() const LLVM_READONLY
Definition: CommentLexer.h:120
StringRef getUnknownCommandName() const LLVM_READONLY
Definition: CommentLexer.h:109
StringRef getText() const LLVM_READONLY
Definition: CommentLexer.h:98
StringRef getHTMLIdent() const LLVM_READONLY
Definition: CommentLexer.h:183
StringRef getVerbatimBlockText() const LLVM_READONLY
Definition: CommentLexer.h:140
unsigned getVerbatimLineID() const LLVM_READONLY
Definition: CommentLexer.h:151
unsigned getVerbatimBlockID() const LLVM_READONLY
Definition: CommentLexer.h:130
bool is(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:92
SourceLocation getLocation() const LLVM_READONLY
Definition: CommentLexer.h:80
StringRef getVerbatimLineText() const LLVM_READONLY
Definition: CommentLexer.h:161
tok::TokenKind getKind() const LLVM_READONLY
Definition: CommentLexer.h:89
StringRef getHTMLTagStartName() const LLVM_READONLY
Definition: CommentLexer.h:172
StringRef getHTMLTagEndName() const LLVM_READONLY
Definition: CommentLexer.h:205
A verbatim block command (e.
Definition: Comment.h:879
A line of text contained in a verbatim block.
Definition: Comment.h:854
A verbatim line command.
Definition: Comment.h:930
CommandMarkerKind
Describes the syntax that was used in a documentation command.
Definition: Comment.h:38
@ CMK_Backslash
Command started with a backslash character:
Definition: Comment.h:43
@ CMK_At
Command started with an 'at' character:
Definition: Comment.h:49
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
Definition: CharInfo.h:109
#define false
Definition: stdbool.h:22
Information about a single command.
unsigned IsBlockCommand
True if this command is a block command (of any kind).
unsigned IsTParamCommand
True if this command is introducing documentation for a template parameter (\tparam or an alias).
unsigned IsVerbatimBlockEndCommand
True if this command is an end command for a verbatim-like block.
unsigned IsParamCommand
True if this command is introducing documentation for a function parameter (\param or an alias).
unsigned IsInlineCommand
True if this command is a inline command (of any kind).
unsigned IsUnknownCommand
True if this command is unknown.
unsigned NumArgs
Number of word-like arguments for a given block command, except for \param and \tparam commands – the...