1 //===- unittests/AST/CommentParser.cpp ------ Comment parser tests --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/AST/CommentParser.h"
10 #include "clang/AST/Comment.h"
11 #include "clang/AST/CommentCommandTraits.h"
12 #include "clang/AST/CommentLexer.h"
13 #include "clang/AST/CommentSema.h"
14 #include "clang/Basic/CommentOptions.h"
15 #include "clang/Basic/Diagnostic.h"
16 #include "clang/Basic/DiagnosticOptions.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Support/Allocator.h"
21 #include "gtest/gtest.h"
24 using namespace clang
;
31 const bool MY_DEBUG
= true;
33 class CommentParserTest
: public ::testing::Test
{
36 : FileMgr(FileMgrOpts
),
37 DiagID(new DiagnosticIDs()),
38 Diags(DiagID
, new DiagnosticOptions
, new IgnoringDiagConsumer()),
39 SourceMgr(Diags
, FileMgr
),
40 Traits(Allocator
, CommentOptions()) {
43 FileSystemOptions FileMgrOpts
;
45 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID
;
46 DiagnosticsEngine Diags
;
47 SourceManager SourceMgr
;
48 llvm::BumpPtrAllocator Allocator
;
51 FullComment
*parseString(const char *Source
);
54 FullComment
*CommentParserTest::parseString(const char *Source
) {
55 std::unique_ptr
<MemoryBuffer
> Buf
= MemoryBuffer::getMemBuffer(Source
);
56 FileID File
= SourceMgr
.createFileID(std::move(Buf
));
57 SourceLocation Begin
= SourceMgr
.getLocForStartOfFile(File
);
59 Lexer
L(Allocator
, Diags
, Traits
, Begin
, Source
, Source
+ strlen(Source
));
61 Sema
S(Allocator
, SourceMgr
, Diags
, Traits
, /*PP=*/ nullptr);
62 Parser
P(L
, S
, Allocator
, SourceMgr
, Diags
, Traits
);
63 FullComment
*FC
= P
.parseFullComment();
66 llvm::errs() << "=== Source:\n" << Source
<< "\n=== AST:\n";
78 ::testing::AssertionResult
HasChildCount(const Comment
*C
, size_t Count
) {
80 return ::testing::AssertionFailure() << "Comment is NULL";
82 if (Count
!= C
->child_count())
83 return ::testing::AssertionFailure()
84 << "Count = " << Count
85 << ", child_count = " << C
->child_count();
87 return ::testing::AssertionSuccess();
91 ::testing::AssertionResult
GetChildAt(const Comment
*C
,
95 return ::testing::AssertionFailure() << "Comment is NULL";
97 if (Idx
>= C
->child_count())
98 return ::testing::AssertionFailure()
99 << "Idx out of range. Idx = " << Idx
100 << ", child_count = " << C
->child_count();
102 Comment::child_iterator I
= C
->child_begin() + Idx
;
103 Comment
*CommentChild
= *I
;
105 return ::testing::AssertionFailure() << "Child is NULL";
107 Child
= dyn_cast
<T
>(CommentChild
);
109 return ::testing::AssertionFailure()
110 << "Child is not of requested type, but a "
111 << CommentChild
->getCommentKindName();
113 return ::testing::AssertionSuccess();
116 ::testing::AssertionResult
HasTextAt(const Comment
*C
,
120 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, TC
);
124 StringRef ActualText
= TC
->getText();
125 if (ActualText
!= Text
)
126 return ::testing::AssertionFailure()
127 << "TextComment has text \"" << ActualText
.str() << "\", "
128 "expected \"" << Text
.str() << "\"";
130 if (TC
->hasTrailingNewline())
131 return ::testing::AssertionFailure()
132 << "TextComment has a trailing newline";
134 return ::testing::AssertionSuccess();
137 ::testing::AssertionResult
HasTextWithNewlineAt(const Comment
*C
,
141 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, TC
);
145 StringRef ActualText
= TC
->getText();
146 if (ActualText
!= Text
)
147 return ::testing::AssertionFailure()
148 << "TextComment has text \"" << ActualText
.str() << "\", "
149 "expected \"" << Text
.str() << "\"";
151 if (!TC
->hasTrailingNewline())
152 return ::testing::AssertionFailure()
153 << "TextComment has no trailing newline";
155 return ::testing::AssertionSuccess();
158 ::testing::AssertionResult
HasBlockCommandAt(const Comment
*C
,
159 const CommandTraits
&Traits
,
161 BlockCommandComment
*&BCC
,
163 ParagraphComment
*&Paragraph
) {
164 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, BCC
);
168 StringRef ActualName
= BCC
->getCommandName(Traits
);
169 if (ActualName
!= Name
)
170 return ::testing::AssertionFailure()
171 << "BlockCommandComment has name \"" << ActualName
.str() << "\", "
172 "expected \"" << Name
.str() << "\"";
174 Paragraph
= BCC
->getParagraph();
176 return ::testing::AssertionSuccess();
179 ::testing::AssertionResult
HasParamCommandAt(
181 const CommandTraits
&Traits
,
183 ParamCommandComment
*&PCC
,
184 StringRef CommandName
,
185 ParamCommandComment::PassDirection Direction
,
186 bool IsDirectionExplicit
,
188 ParagraphComment
*&Paragraph
) {
189 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, PCC
);
193 StringRef ActualCommandName
= PCC
->getCommandName(Traits
);
194 if (ActualCommandName
!= CommandName
)
195 return ::testing::AssertionFailure()
196 << "ParamCommandComment has name \"" << ActualCommandName
.str() << "\", "
197 "expected \"" << CommandName
.str() << "\"";
199 if (PCC
->getDirection() != Direction
)
200 return ::testing::AssertionFailure()
201 << "ParamCommandComment has direction " << PCC
->getDirection() << ", "
202 "expected " << Direction
;
204 if (PCC
->isDirectionExplicit() != IsDirectionExplicit
)
205 return ::testing::AssertionFailure()
206 << "ParamCommandComment has "
207 << (PCC
->isDirectionExplicit() ? "explicit" : "implicit")
209 "expected " << (IsDirectionExplicit
? "explicit" : "implicit");
211 if (!ParamName
.empty() && !PCC
->hasParamName())
212 return ::testing::AssertionFailure()
213 << "ParamCommandComment has no parameter name";
215 StringRef ActualParamName
= PCC
->hasParamName() ? PCC
->getParamNameAsWritten() : "";
216 if (ActualParamName
!= ParamName
)
217 return ::testing::AssertionFailure()
218 << "ParamCommandComment has parameter name \"" << ActualParamName
.str()
220 "expected \"" << ParamName
.str() << "\"";
222 Paragraph
= PCC
->getParagraph();
224 return ::testing::AssertionSuccess();
227 ::testing::AssertionResult
HasTParamCommandAt(
229 const CommandTraits
&Traits
,
231 TParamCommandComment
*&TPCC
,
232 StringRef CommandName
,
234 ParagraphComment
*&Paragraph
) {
235 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, TPCC
);
239 StringRef ActualCommandName
= TPCC
->getCommandName(Traits
);
240 if (ActualCommandName
!= CommandName
)
241 return ::testing::AssertionFailure()
242 << "TParamCommandComment has name \"" << ActualCommandName
.str() << "\", "
243 "expected \"" << CommandName
.str() << "\"";
245 if (!ParamName
.empty() && !TPCC
->hasParamName())
246 return ::testing::AssertionFailure()
247 << "TParamCommandComment has no parameter name";
249 StringRef ActualParamName
= TPCC
->hasParamName() ? TPCC
->getParamNameAsWritten() : "";
250 if (ActualParamName
!= ParamName
)
251 return ::testing::AssertionFailure()
252 << "TParamCommandComment has parameter name \"" << ActualParamName
.str()
254 "expected \"" << ParamName
.str() << "\"";
256 Paragraph
= TPCC
->getParagraph();
258 return ::testing::AssertionSuccess();
261 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
262 const CommandTraits
&Traits
,
264 InlineCommandComment
*&ICC
,
266 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, ICC
);
270 StringRef ActualName
= ICC
->getCommandName(Traits
);
271 if (ActualName
!= Name
)
272 return ::testing::AssertionFailure()
273 << "InlineCommandComment has name \"" << ActualName
.str() << "\", "
274 "expected \"" << Name
.str() << "\"";
276 return ::testing::AssertionSuccess();
281 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
282 const CommandTraits
&Traits
,
284 InlineCommandComment
*&ICC
,
287 ::testing::AssertionResult AR
= HasInlineCommandAt(C
, Traits
, Idx
, ICC
, Name
);
291 if (ICC
->getNumArgs() != 0)
292 return ::testing::AssertionFailure()
293 << "InlineCommandComment has " << ICC
->getNumArgs() << " arg(s), "
296 return ::testing::AssertionSuccess();
299 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
300 const CommandTraits
&Traits
,
302 InlineCommandComment
*&ICC
,
305 ::testing::AssertionResult AR
= HasInlineCommandAt(C
, Traits
, Idx
, ICC
, Name
);
309 if (ICC
->getNumArgs() != 1)
310 return ::testing::AssertionFailure()
311 << "InlineCommandComment has " << ICC
->getNumArgs() << " arg(s), "
314 StringRef ActualArg
= ICC
->getArgText(0);
315 if (ActualArg
!= Arg
)
316 return ::testing::AssertionFailure()
317 << "InlineCommandComment has argument \"" << ActualArg
.str() << "\", "
318 "expected \"" << Arg
.str() << "\"";
320 return ::testing::AssertionSuccess();
323 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
325 HTMLStartTagComment
*&HST
,
327 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, HST
);
331 StringRef ActualTagName
= HST
->getTagName();
332 if (ActualTagName
!= TagName
)
333 return ::testing::AssertionFailure()
334 << "HTMLStartTagComment has name \"" << ActualTagName
.str() << "\", "
335 "expected \"" << TagName
.str() << "\"";
337 return ::testing::AssertionSuccess();
340 struct SelfClosing
{};
342 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
344 HTMLStartTagComment
*&HST
,
347 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
351 if (!HST
->isSelfClosing())
352 return ::testing::AssertionFailure()
353 << "HTMLStartTagComment is not self-closing";
355 return ::testing::AssertionSuccess();
361 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
363 HTMLStartTagComment
*&HST
,
366 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
370 if (HST
->isSelfClosing())
371 return ::testing::AssertionFailure()
372 << "HTMLStartTagComment is self-closing";
374 if (HST
->getNumAttrs() != 0)
375 return ::testing::AssertionFailure()
376 << "HTMLStartTagComment has " << HST
->getNumAttrs() << " attr(s), "
379 return ::testing::AssertionSuccess();
382 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
384 HTMLStartTagComment
*&HST
,
387 StringRef AttrValue
) {
388 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
392 if (HST
->isSelfClosing())
393 return ::testing::AssertionFailure()
394 << "HTMLStartTagComment is self-closing";
396 if (HST
->getNumAttrs() != 1)
397 return ::testing::AssertionFailure()
398 << "HTMLStartTagComment has " << HST
->getNumAttrs() << " attr(s), "
401 StringRef ActualName
= HST
->getAttr(0).Name
;
402 if (ActualName
!= AttrName
)
403 return ::testing::AssertionFailure()
404 << "HTMLStartTagComment has attr \"" << ActualName
.str() << "\", "
405 "expected \"" << AttrName
.str() << "\"";
407 StringRef ActualValue
= HST
->getAttr(0).Value
;
408 if (ActualValue
!= AttrValue
)
409 return ::testing::AssertionFailure()
410 << "HTMLStartTagComment has attr value \"" << ActualValue
.str() << "\", "
411 "expected \"" << AttrValue
.str() << "\"";
413 return ::testing::AssertionSuccess();
416 ::testing::AssertionResult
HasHTMLEndTagAt(const Comment
*C
,
418 HTMLEndTagComment
*&HET
,
420 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, HET
);
424 StringRef ActualTagName
= HET
->getTagName();
425 if (ActualTagName
!= TagName
)
426 return ::testing::AssertionFailure()
427 << "HTMLEndTagComment has name \"" << ActualTagName
.str() << "\", "
428 "expected \"" << TagName
.str() << "\"";
430 return ::testing::AssertionSuccess();
433 ::testing::AssertionResult
HasParagraphCommentAt(const Comment
*C
,
436 ParagraphComment
*PC
;
439 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, PC
);
445 ::testing::AssertionResult AR
= HasChildCount(PC
, 1);
451 ::testing::AssertionResult AR
= HasTextAt(PC
, 0, Text
);
456 return ::testing::AssertionSuccess();
459 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
460 const CommandTraits
&Traits
,
462 VerbatimBlockComment
*&VBC
,
464 StringRef CloseName
) {
465 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, VBC
);
469 StringRef ActualName
= VBC
->getCommandName(Traits
);
470 if (ActualName
!= Name
)
471 return ::testing::AssertionFailure()
472 << "VerbatimBlockComment has name \"" << ActualName
.str() << "\", "
473 "expected \"" << Name
.str() << "\"";
475 StringRef ActualCloseName
= VBC
->getCloseName();
476 if (ActualCloseName
!= CloseName
)
477 return ::testing::AssertionFailure()
478 << "VerbatimBlockComment has closing command name \""
479 << ActualCloseName
.str() << "\", "
480 "expected \"" << CloseName
.str() << "\"";
482 return ::testing::AssertionSuccess();
488 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
489 const CommandTraits
&Traits
,
491 VerbatimBlockComment
*&VBC
,
495 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
500 if (VBC
->getNumLines() != 0)
501 return ::testing::AssertionFailure()
502 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
505 return ::testing::AssertionSuccess();
508 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
509 const CommandTraits
&Traits
,
511 VerbatimBlockComment
*&VBC
,
516 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
521 if (VBC
->getNumLines() != 1)
522 return ::testing::AssertionFailure()
523 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
526 StringRef ActualLine0
= VBC
->getText(0);
527 if (ActualLine0
!= Line0
)
528 return ::testing::AssertionFailure()
529 << "VerbatimBlockComment has lines[0] \"" << ActualLine0
.str() << "\", "
530 "expected \"" << Line0
.str() << "\"";
532 return ::testing::AssertionSuccess();
535 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
536 const CommandTraits
&Traits
,
538 VerbatimBlockComment
*&VBC
,
544 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
549 if (VBC
->getNumLines() != 2)
550 return ::testing::AssertionFailure()
551 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
554 StringRef ActualLine0
= VBC
->getText(0);
555 if (ActualLine0
!= Line0
)
556 return ::testing::AssertionFailure()
557 << "VerbatimBlockComment has lines[0] \"" << ActualLine0
.str() << "\", "
558 "expected \"" << Line0
.str() << "\"";
560 StringRef ActualLine1
= VBC
->getText(1);
561 if (ActualLine1
!= Line1
)
562 return ::testing::AssertionFailure()
563 << "VerbatimBlockComment has lines[1] \"" << ActualLine1
.str() << "\", "
564 "expected \"" << Line1
.str() << "\"";
566 return ::testing::AssertionSuccess();
569 ::testing::AssertionResult
HasVerbatimLineAt(const Comment
*C
,
570 const CommandTraits
&Traits
,
572 VerbatimLineComment
*&VLC
,
575 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, VLC
);
579 StringRef ActualName
= VLC
->getCommandName(Traits
);
580 if (ActualName
!= Name
)
581 return ::testing::AssertionFailure()
582 << "VerbatimLineComment has name \"" << ActualName
.str() << "\", "
583 "expected \"" << Name
.str() << "\"";
585 StringRef ActualText
= VLC
->getText();
586 if (ActualText
!= Text
)
587 return ::testing::AssertionFailure()
588 << "VerbatimLineComment has text \"" << ActualText
.str() << "\", "
589 "expected \"" << Text
.str() << "\"";
591 return ::testing::AssertionSuccess();
595 TEST_F(CommentParserTest
, Basic1
) {
596 const char *Source
= "//";
598 FullComment
*FC
= parseString(Source
);
599 ASSERT_TRUE(HasChildCount(FC
, 0));
602 TEST_F(CommentParserTest
, Basic2
) {
603 const char *Source
= "// Meow";
605 FullComment
*FC
= parseString(Source
);
606 ASSERT_TRUE(HasChildCount(FC
, 1));
608 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " Meow"));
611 TEST_F(CommentParserTest
, Basic3
) {
616 FullComment
*FC
= parseString(Source
);
617 ASSERT_TRUE(HasChildCount(FC
, 1));
620 ParagraphComment
*PC
;
621 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
623 ASSERT_TRUE(HasChildCount(PC
, 2));
624 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 0, " Aaa"));
625 ASSERT_TRUE(HasTextAt(PC
, 1, " Bbb"));
629 TEST_F(CommentParserTest
, ParagraphSplitting1
) {
630 const char *Sources
[] = {
667 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
668 FullComment
*FC
= parseString(Sources
[i
]);
669 ASSERT_TRUE(HasChildCount(FC
, 2));
671 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " Aaa"));
672 ASSERT_TRUE(HasParagraphCommentAt(FC
, 1, " Bbb"));
676 TEST_F(CommentParserTest
, Paragraph1
) {
682 FullComment
*FC
= parseString(Source
);
683 ASSERT_TRUE(HasChildCount(FC
, 3));
685 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
687 BlockCommandComment
*BCC
;
688 ParagraphComment
*PC
;
689 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
691 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " Aaa"));
693 ASSERT_TRUE(HasParagraphCommentAt(FC
, 2, " Bbb"));
696 TEST_F(CommentParserTest
, Paragraph2
) {
697 const char *Source
= "// \\brief \\author";
699 FullComment
*FC
= parseString(Source
);
700 ASSERT_TRUE(HasChildCount(FC
, 3));
702 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
704 BlockCommandComment
*BCC
;
705 ParagraphComment
*PC
;
706 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
708 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " "));
711 BlockCommandComment
*BCC
;
712 ParagraphComment
*PC
;
713 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "author", PC
));
715 ASSERT_TRUE(GetChildAt(BCC
, 0, PC
));
716 ASSERT_TRUE(HasChildCount(PC
, 0));
720 TEST_F(CommentParserTest
, Paragraph3
) {
726 FullComment
*FC
= parseString(Source
);
727 ASSERT_TRUE(HasChildCount(FC
, 3));
729 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
731 BlockCommandComment
*BCC
;
732 ParagraphComment
*PC
;
733 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
735 ASSERT_TRUE(GetChildAt(BCC
, 0, PC
));
736 ASSERT_TRUE(HasChildCount(PC
, 2));
737 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 0, " Aaa"));
738 ASSERT_TRUE(HasTextAt(PC
, 1, " Bbb "));
741 BlockCommandComment
*BCC
;
742 ParagraphComment
*PC
;
743 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "author", PC
));
745 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " Ccc"));
749 TEST_F(CommentParserTest
, ParamCommand1
) {
750 const char *Source
= "// \\param aaa";
752 FullComment
*FC
= parseString(Source
);
753 ASSERT_TRUE(HasChildCount(FC
, 2));
755 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
757 ParamCommandComment
*PCC
;
758 ParagraphComment
*PC
;
759 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
760 ParamCommandComment::In
,
761 /* IsDirectionExplicit = */ false,
763 ASSERT_TRUE(HasChildCount(PCC
, 1));
764 ASSERT_TRUE(HasChildCount(PC
, 0));
768 TEST_F(CommentParserTest
, ParamCommand2
) {
769 const char *Source
= "// \\param\\brief";
771 FullComment
*FC
= parseString(Source
);
772 ASSERT_TRUE(HasChildCount(FC
, 3));
774 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
776 ParamCommandComment
*PCC
;
777 ParagraphComment
*PC
;
778 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
779 ParamCommandComment::In
,
780 /* IsDirectionExplicit = */ false,
782 ASSERT_TRUE(HasChildCount(PCC
, 1));
783 ASSERT_TRUE(HasChildCount(PC
, 0));
786 BlockCommandComment
*BCC
;
787 ParagraphComment
*PC
;
788 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "brief", PC
));
789 ASSERT_TRUE(HasChildCount(PC
, 0));
793 TEST_F(CommentParserTest
, ParamCommand3
) {
794 const char *Sources
[] = {
795 "// \\param aaa Bbb\n",
804 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
805 FullComment
*FC
= parseString(Sources
[i
]);
806 ASSERT_TRUE(HasChildCount(FC
, 2));
808 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
810 ParamCommandComment
*PCC
;
811 ParagraphComment
*PC
;
812 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
813 ParamCommandComment::In
,
814 /* IsDirectionExplicit = */ false,
816 ASSERT_TRUE(HasChildCount(PCC
, 1));
817 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
822 TEST_F(CommentParserTest
, ParamCommand4
) {
823 const char *Sources
[] = {
824 "// \\param [in] aaa Bbb\n",
825 "// \\param[in] aaa Bbb\n",
827 "// [in] aaa Bbb\n"),
830 ("// \\param [in] aaa\n"
834 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
835 FullComment
*FC
= parseString(Sources
[i
]);
836 ASSERT_TRUE(HasChildCount(FC
, 2));
838 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
840 ParamCommandComment
*PCC
;
841 ParagraphComment
*PC
;
842 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
843 ParamCommandComment::In
,
844 /* IsDirectionExplicit = */ true,
846 ASSERT_TRUE(HasChildCount(PCC
, 1));
847 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
852 TEST_F(CommentParserTest
, ParamCommand5
) {
853 const char *Sources
[] = {
854 "// \\param [out] aaa Bbb\n",
855 "// \\param[out] aaa Bbb\n",
857 "// [out] aaa Bbb\n"),
858 ("// \\param [out]\n"
860 ("// \\param [out] aaa\n"
864 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
865 FullComment
*FC
= parseString(Sources
[i
]);
866 ASSERT_TRUE(HasChildCount(FC
, 2));
868 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
870 ParamCommandComment
*PCC
;
871 ParagraphComment
*PC
;
872 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
873 ParamCommandComment::Out
,
874 /* IsDirectionExplicit = */ true,
876 ASSERT_TRUE(HasChildCount(PCC
, 1));
877 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
882 TEST_F(CommentParserTest
, ParamCommand6
) {
883 const char *Sources
[] = {
884 "// \\param [in,out] aaa Bbb\n",
885 "// \\param[in,out] aaa Bbb\n",
886 "// \\param [in, out] aaa Bbb\n",
889 "// \\param [in,out]\n"
891 "// \\param [in,out] aaa\n"
895 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
896 FullComment
*FC
= parseString(Sources
[i
]);
897 ASSERT_TRUE(HasChildCount(FC
, 2));
899 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
901 ParamCommandComment
*PCC
;
902 ParagraphComment
*PC
;
903 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
904 ParamCommandComment::InOut
,
905 /* IsDirectionExplicit = */ true,
907 ASSERT_TRUE(HasChildCount(PCC
, 1));
908 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
913 TEST_F(CommentParserTest
, ParamCommand7
) {
915 "// \\param aaa \\% Bbb \\$ ccc\n";
917 FullComment
*FC
= parseString(Source
);
918 ASSERT_TRUE(HasChildCount(FC
, 2));
920 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
922 ParamCommandComment
*PCC
;
923 ParagraphComment
*PC
;
924 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
925 ParamCommandComment::In
,
926 /* IsDirectionExplicit = */ false,
928 ASSERT_TRUE(HasChildCount(PCC
, 1));
930 ASSERT_TRUE(HasChildCount(PC
, 5));
931 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
932 ASSERT_TRUE(HasTextAt(PC
, 1, "%"));
933 ASSERT_TRUE(HasTextAt(PC
, 2, " Bbb "));
934 ASSERT_TRUE(HasTextAt(PC
, 3, "$"));
935 ASSERT_TRUE(HasTextAt(PC
, 4, " ccc"));
939 TEST_F(CommentParserTest
, TParamCommand1
) {
940 const char *Sources
[] = {
941 "// \\tparam aaa Bbb\n",
950 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
951 FullComment
*FC
= parseString(Sources
[i
]);
952 ASSERT_TRUE(HasChildCount(FC
, 2));
954 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
956 TParamCommandComment
*TPCC
;
957 ParagraphComment
*PC
;
958 ASSERT_TRUE(HasTParamCommandAt(FC
, Traits
, 1, TPCC
, "tparam",
960 ASSERT_TRUE(HasChildCount(TPCC
, 1));
961 ASSERT_TRUE(HasParagraphCommentAt(TPCC
, 0, " Bbb"));
966 TEST_F(CommentParserTest
, TParamCommand2
) {
967 const char *Source
= "// \\tparam\\brief";
969 FullComment
*FC
= parseString(Source
);
970 ASSERT_TRUE(HasChildCount(FC
, 3));
972 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
974 TParamCommandComment
*TPCC
;
975 ParagraphComment
*PC
;
976 ASSERT_TRUE(HasTParamCommandAt(FC
, Traits
, 1, TPCC
, "tparam", "", PC
));
977 ASSERT_TRUE(HasChildCount(TPCC
, 1));
978 ASSERT_TRUE(HasChildCount(PC
, 0));
981 BlockCommandComment
*BCC
;
982 ParagraphComment
*PC
;
983 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "brief", PC
));
984 ASSERT_TRUE(HasChildCount(PC
, 0));
989 TEST_F(CommentParserTest
, InlineCommand1
) {
990 const char *Source
= "// \\c";
992 FullComment
*FC
= parseString(Source
);
993 ASSERT_TRUE(HasChildCount(FC
, 1));
996 ParagraphComment
*PC
;
997 InlineCommandComment
*ICC
;
998 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1000 ASSERT_TRUE(HasChildCount(PC
, 2));
1001 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1002 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", NoArgs()));
1006 TEST_F(CommentParserTest
, InlineCommand2
) {
1007 const char *Source
= "// \\c ";
1009 FullComment
*FC
= parseString(Source
);
1010 ASSERT_TRUE(HasChildCount(FC
, 1));
1013 ParagraphComment
*PC
;
1014 InlineCommandComment
*ICC
;
1015 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1017 ASSERT_TRUE(HasChildCount(PC
, 3));
1018 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1019 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", NoArgs()));
1020 ASSERT_TRUE(HasTextAt(PC
, 2, " "));
1024 TEST_F(CommentParserTest
, InlineCommand3
) {
1025 const char *Source
= "// \\c aaa\n";
1027 FullComment
*FC
= parseString(Source
);
1028 ASSERT_TRUE(HasChildCount(FC
, 1));
1031 ParagraphComment
*PC
;
1032 InlineCommandComment
*ICC
;
1033 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1035 ASSERT_TRUE(HasChildCount(PC
, 2));
1036 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1037 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", "aaa"));
1041 TEST_F(CommentParserTest
, InlineCommand4
) {
1042 const char *Source
= "// \\c aaa bbb";
1044 FullComment
*FC
= parseString(Source
);
1045 ASSERT_TRUE(HasChildCount(FC
, 1));
1048 ParagraphComment
*PC
;
1049 InlineCommandComment
*ICC
;
1050 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1052 ASSERT_TRUE(HasChildCount(PC
, 3));
1053 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1054 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", "aaa"));
1055 ASSERT_TRUE(HasTextAt(PC
, 2, " bbb"));
1059 TEST_F(CommentParserTest
, InlineCommand5
) {
1060 const char *Source
= "// \\unknown aaa\n";
1062 FullComment
*FC
= parseString(Source
);
1063 ASSERT_TRUE(HasChildCount(FC
, 1));
1066 ParagraphComment
*PC
;
1067 InlineCommandComment
*ICC
;
1068 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1070 ASSERT_TRUE(HasChildCount(PC
, 3));
1071 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1072 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "unknown", NoArgs()));
1073 ASSERT_TRUE(HasTextAt(PC
, 2, " aaa"));
1077 TEST_F(CommentParserTest
, HTML1
) {
1078 const char *Sources
[] = {
1084 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1085 FullComment
*FC
= parseString(Sources
[i
]);
1086 ASSERT_TRUE(HasChildCount(FC
, 1));
1089 ParagraphComment
*PC
;
1090 HTMLStartTagComment
*HST
;
1091 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1093 ASSERT_TRUE(HasChildCount(PC
, 2));
1094 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1095 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", NoAttrs()));
1100 TEST_F(CommentParserTest
, HTML2
) {
1101 const char *Sources
[] = {
1106 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1107 FullComment
*FC
= parseString(Sources
[i
]);
1108 ASSERT_TRUE(HasChildCount(FC
, 1));
1111 ParagraphComment
*PC
;
1112 HTMLStartTagComment
*HST
;
1113 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1115 ASSERT_TRUE(HasChildCount(PC
, 2));
1116 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1117 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "br", SelfClosing()));
1122 TEST_F(CommentParserTest
, HTML3
) {
1123 const char *Sources
[] = {
1130 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1131 FullComment
*FC
= parseString(Sources
[i
]);
1132 ASSERT_TRUE(HasChildCount(FC
, 1));
1135 ParagraphComment
*PC
;
1136 HTMLStartTagComment
*HST
;
1137 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1139 ASSERT_TRUE(HasChildCount(PC
, 2));
1140 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1141 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", "href", ""));
1146 TEST_F(CommentParserTest
, HTML4
) {
1147 const char *Sources
[] = {
1148 "// <a href=\"bbb\"",
1149 "// <a href=\"bbb\">",
1152 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1153 FullComment
*FC
= parseString(Sources
[i
]);
1154 ASSERT_TRUE(HasChildCount(FC
, 1));
1157 ParagraphComment
*PC
;
1158 HTMLStartTagComment
*HST
;
1159 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1161 ASSERT_TRUE(HasChildCount(PC
, 2));
1162 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1163 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", "href", "bbb"));
1168 TEST_F(CommentParserTest
, HTML5
) {
1169 const char *Sources
[] = {
1175 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1176 FullComment
*FC
= parseString(Sources
[i
]);
1177 ASSERT_TRUE(HasChildCount(FC
, 1));
1180 ParagraphComment
*PC
;
1181 HTMLEndTagComment
*HET
;
1182 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1184 ASSERT_TRUE(HasChildCount(PC
, 2));
1185 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1186 ASSERT_TRUE(HasHTMLEndTagAt(PC
, 1, HET
, "a"));
1191 TEST_F(CommentParserTest
, HTML6
) {
1192 const char *Source
=
1198 FullComment
*FC
= parseString(Source
);
1199 ASSERT_TRUE(HasChildCount(FC
, 1));
1202 ParagraphComment
*PC
;
1203 HTMLStartTagComment
*HST
;
1204 HTMLEndTagComment
*HET
;
1205 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1207 ASSERT_TRUE(HasChildCount(PC
, 6));
1208 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1209 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "pre", NoAttrs()));
1210 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 2, " Aaa"));
1211 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 3, " Bbb"));
1212 ASSERT_TRUE(HasTextAt(PC
, 4, " "));
1213 ASSERT_TRUE(HasHTMLEndTagAt(PC
, 5, HET
, "pre"));
1217 TEST_F(CommentParserTest
, VerbatimBlock1
) {
1218 const char *Source
= "// \\verbatim\\endverbatim\n";
1220 FullComment
*FC
= parseString(Source
);
1221 ASSERT_TRUE(HasChildCount(FC
, 2));
1223 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1225 VerbatimBlockComment
*VCC
;
1226 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VCC
,
1227 "verbatim", "endverbatim",
1232 TEST_F(CommentParserTest
, VerbatimBlock2
) {
1233 const char *Source
= "// \\verbatim Aaa \\endverbatim\n";
1235 FullComment
*FC
= parseString(Source
);
1236 ASSERT_TRUE(HasChildCount(FC
, 2));
1238 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1240 VerbatimBlockComment
*VBC
;
1241 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1242 "verbatim", "endverbatim",
1247 TEST_F(CommentParserTest
, VerbatimBlock3
) {
1248 const char *Source
= "// \\verbatim Aaa\n";
1250 FullComment
*FC
= parseString(Source
);
1251 ASSERT_TRUE(HasChildCount(FC
, 2));
1253 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1255 VerbatimBlockComment
*VBC
;
1256 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
, "verbatim", "",
1261 TEST_F(CommentParserTest
, VerbatimBlock4
) {
1262 const char *Source
=
1264 "//\\endverbatim\n";
1266 FullComment
*FC
= parseString(Source
);
1267 ASSERT_TRUE(HasChildCount(FC
, 1));
1270 VerbatimBlockComment
*VBC
;
1271 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 0, VBC
,
1272 "verbatim", "endverbatim",
1277 TEST_F(CommentParserTest
, VerbatimBlock5
) {
1278 const char *Sources
[] = {
1281 "//\\endverbatim\n",
1288 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1289 FullComment
*FC
= parseString(Sources
[i
]);
1290 ASSERT_TRUE(HasChildCount(FC
, 1));
1293 VerbatimBlockComment
*VBC
;
1294 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 0, VBC
,
1295 "verbatim", "endverbatim",
1301 TEST_F(CommentParserTest
, VerbatimBlock6
) {
1302 const char *Sources
[] = {
1305 "// \\endverbatim\n",
1309 " * \\endverbatim*/"
1312 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1313 FullComment
*FC
= parseString(Sources
[i
]);
1314 ASSERT_TRUE(HasChildCount(FC
, 2));
1316 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1318 VerbatimBlockComment
*VBC
;
1319 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1320 "verbatim", "endverbatim",
1326 TEST_F(CommentParserTest
, VerbatimBlock7
) {
1327 const char *Sources
[] = {
1331 "// \\endverbatim\n",
1336 " * \\endverbatim*/"
1339 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1340 FullComment
*FC
= parseString(Sources
[i
]);
1341 ASSERT_TRUE(HasChildCount(FC
, 2));
1343 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1345 VerbatimBlockComment
*VBC
;
1346 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1347 "verbatim", "endverbatim",
1348 Lines(), " Aaa", " Bbb"));
1353 TEST_F(CommentParserTest
, VerbatimBlock8
) {
1354 const char *Sources
[] = {
1359 "// \\endverbatim\n",
1365 " * \\endverbatim*/"
1367 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1368 FullComment
*FC
= parseString(Sources
[i
]);
1369 ASSERT_TRUE(HasChildCount(FC
, 2));
1371 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1373 VerbatimBlockComment
*VBC
;
1374 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1375 "verbatim", "endverbatim"));
1376 ASSERT_EQ(3U, VBC
->getNumLines());
1377 ASSERT_EQ(" Aaa", VBC
->getText(0));
1378 ASSERT_EQ("", VBC
->getText(1));
1379 ASSERT_EQ(" Bbb", VBC
->getText(2));
1384 TEST_F(CommentParserTest
, VerbatimLine1
) {
1385 const char *Sources
[] = {
1390 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1391 FullComment
*FC
= parseString(Sources
[i
]);
1392 ASSERT_TRUE(HasChildCount(FC
, 2));
1394 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1396 VerbatimLineComment
*VLC
;
1397 ASSERT_TRUE(HasVerbatimLineAt(FC
, Traits
, 1, VLC
, "fn", ""));
1402 TEST_F(CommentParserTest
, VerbatimLine2
) {
1403 const char *Sources
[] = {
1404 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
1405 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
1408 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1409 FullComment
*FC
= parseString(Sources
[i
]);
1410 ASSERT_TRUE(HasChildCount(FC
, 2));
1412 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1414 VerbatimLineComment
*VLC
;
1415 ASSERT_TRUE(HasVerbatimLineAt(FC
, Traits
, 1, VLC
, "fn",
1416 " void *foo(const char *zzz = \"\\$\");"));
1421 TEST_F(CommentParserTest
, Deprecated
) {
1422 const char *Sources
[] = {
1423 "/** @deprecated*/",
1427 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1428 FullComment
*FC
= parseString(Sources
[i
]);
1429 ASSERT_TRUE(HasChildCount(FC
, 2));
1431 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1433 BlockCommandComment
*BCC
;
1434 ParagraphComment
*PC
;
1435 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "deprecated", PC
));
1436 ASSERT_TRUE(HasChildCount(PC
, 0));
1441 } // unnamed namespace
1443 } // end namespace comments
1444 } // end namespace clang