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
180 HasParamCommandAt(const Comment
*C
, const CommandTraits
&Traits
, size_t Idx
,
181 ParamCommandComment
*&PCC
, StringRef CommandName
,
182 ParamCommandPassDirection Direction
, bool IsDirectionExplicit
,
183 StringRef ParamName
, ParagraphComment
*&Paragraph
) {
184 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, PCC
);
188 StringRef ActualCommandName
= PCC
->getCommandName(Traits
);
189 if (ActualCommandName
!= CommandName
)
190 return ::testing::AssertionFailure()
191 << "ParamCommandComment has name \"" << ActualCommandName
.str() << "\", "
192 "expected \"" << CommandName
.str() << "\"";
194 if (PCC
->getDirection() != Direction
)
195 return ::testing::AssertionFailure()
196 << "ParamCommandComment has direction "
197 << llvm::to_underlying(PCC
->getDirection()) << ", expected "
198 << llvm::to_underlying(Direction
);
200 if (PCC
->isDirectionExplicit() != IsDirectionExplicit
)
201 return ::testing::AssertionFailure()
202 << "ParamCommandComment has "
203 << (PCC
->isDirectionExplicit() ? "explicit" : "implicit")
205 "expected " << (IsDirectionExplicit
? "explicit" : "implicit");
207 if (!ParamName
.empty() && !PCC
->hasParamName())
208 return ::testing::AssertionFailure()
209 << "ParamCommandComment has no parameter name";
211 StringRef ActualParamName
= PCC
->hasParamName() ? PCC
->getParamNameAsWritten() : "";
212 if (ActualParamName
!= ParamName
)
213 return ::testing::AssertionFailure()
214 << "ParamCommandComment has parameter name \"" << ActualParamName
.str()
216 "expected \"" << ParamName
.str() << "\"";
218 Paragraph
= PCC
->getParagraph();
220 return ::testing::AssertionSuccess();
223 ::testing::AssertionResult
HasTParamCommandAt(
225 const CommandTraits
&Traits
,
227 TParamCommandComment
*&TPCC
,
228 StringRef CommandName
,
230 ParagraphComment
*&Paragraph
) {
231 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, TPCC
);
235 StringRef ActualCommandName
= TPCC
->getCommandName(Traits
);
236 if (ActualCommandName
!= CommandName
)
237 return ::testing::AssertionFailure()
238 << "TParamCommandComment has name \"" << ActualCommandName
.str() << "\", "
239 "expected \"" << CommandName
.str() << "\"";
241 if (!ParamName
.empty() && !TPCC
->hasParamName())
242 return ::testing::AssertionFailure()
243 << "TParamCommandComment has no parameter name";
245 StringRef ActualParamName
= TPCC
->hasParamName() ? TPCC
->getParamNameAsWritten() : "";
246 if (ActualParamName
!= ParamName
)
247 return ::testing::AssertionFailure()
248 << "TParamCommandComment has parameter name \"" << ActualParamName
.str()
250 "expected \"" << ParamName
.str() << "\"";
252 Paragraph
= TPCC
->getParagraph();
254 return ::testing::AssertionSuccess();
257 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
258 const CommandTraits
&Traits
,
260 InlineCommandComment
*&ICC
,
262 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, ICC
);
266 StringRef ActualName
= ICC
->getCommandName(Traits
);
267 if (ActualName
!= Name
)
268 return ::testing::AssertionFailure()
269 << "InlineCommandComment has name \"" << ActualName
.str() << "\", "
270 "expected \"" << Name
.str() << "\"";
272 return ::testing::AssertionSuccess();
277 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
278 const CommandTraits
&Traits
,
280 InlineCommandComment
*&ICC
,
283 ::testing::AssertionResult AR
= HasInlineCommandAt(C
, Traits
, Idx
, ICC
, Name
);
287 if (ICC
->getNumArgs() != 0)
288 return ::testing::AssertionFailure()
289 << "InlineCommandComment has " << ICC
->getNumArgs() << " arg(s), "
292 return ::testing::AssertionSuccess();
295 ::testing::AssertionResult
HasInlineCommandAt(const Comment
*C
,
296 const CommandTraits
&Traits
,
298 InlineCommandComment
*&ICC
,
301 ::testing::AssertionResult AR
= HasInlineCommandAt(C
, Traits
, Idx
, ICC
, Name
);
305 if (ICC
->getNumArgs() != 1)
306 return ::testing::AssertionFailure()
307 << "InlineCommandComment has " << ICC
->getNumArgs() << " arg(s), "
310 StringRef ActualArg
= ICC
->getArgText(0);
311 if (ActualArg
!= Arg
)
312 return ::testing::AssertionFailure()
313 << "InlineCommandComment has argument \"" << ActualArg
.str() << "\", "
314 "expected \"" << Arg
.str() << "\"";
316 return ::testing::AssertionSuccess();
319 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
321 HTMLStartTagComment
*&HST
,
323 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, HST
);
327 StringRef ActualTagName
= HST
->getTagName();
328 if (ActualTagName
!= TagName
)
329 return ::testing::AssertionFailure()
330 << "HTMLStartTagComment has name \"" << ActualTagName
.str() << "\", "
331 "expected \"" << TagName
.str() << "\"";
333 return ::testing::AssertionSuccess();
336 struct SelfClosing
{};
338 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
340 HTMLStartTagComment
*&HST
,
343 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
347 if (!HST
->isSelfClosing())
348 return ::testing::AssertionFailure()
349 << "HTMLStartTagComment is not self-closing";
351 return ::testing::AssertionSuccess();
357 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
359 HTMLStartTagComment
*&HST
,
362 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
366 if (HST
->isSelfClosing())
367 return ::testing::AssertionFailure()
368 << "HTMLStartTagComment is self-closing";
370 if (HST
->getNumAttrs() != 0)
371 return ::testing::AssertionFailure()
372 << "HTMLStartTagComment has " << HST
->getNumAttrs() << " attr(s), "
375 return ::testing::AssertionSuccess();
378 ::testing::AssertionResult
HasHTMLStartTagAt(const Comment
*C
,
380 HTMLStartTagComment
*&HST
,
383 StringRef AttrValue
) {
384 ::testing::AssertionResult AR
= HasHTMLStartTagAt(C
, Idx
, HST
, TagName
);
388 if (HST
->isSelfClosing())
389 return ::testing::AssertionFailure()
390 << "HTMLStartTagComment is self-closing";
392 if (HST
->getNumAttrs() != 1)
393 return ::testing::AssertionFailure()
394 << "HTMLStartTagComment has " << HST
->getNumAttrs() << " attr(s), "
397 StringRef ActualName
= HST
->getAttr(0).Name
;
398 if (ActualName
!= AttrName
)
399 return ::testing::AssertionFailure()
400 << "HTMLStartTagComment has attr \"" << ActualName
.str() << "\", "
401 "expected \"" << AttrName
.str() << "\"";
403 StringRef ActualValue
= HST
->getAttr(0).Value
;
404 if (ActualValue
!= AttrValue
)
405 return ::testing::AssertionFailure()
406 << "HTMLStartTagComment has attr value \"" << ActualValue
.str() << "\", "
407 "expected \"" << AttrValue
.str() << "\"";
409 return ::testing::AssertionSuccess();
412 ::testing::AssertionResult
HasHTMLEndTagAt(const Comment
*C
,
414 HTMLEndTagComment
*&HET
,
416 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, HET
);
420 StringRef ActualTagName
= HET
->getTagName();
421 if (ActualTagName
!= TagName
)
422 return ::testing::AssertionFailure()
423 << "HTMLEndTagComment has name \"" << ActualTagName
.str() << "\", "
424 "expected \"" << TagName
.str() << "\"";
426 return ::testing::AssertionSuccess();
429 ::testing::AssertionResult
HasParagraphCommentAt(const Comment
*C
,
432 ParagraphComment
*PC
;
435 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, PC
);
441 ::testing::AssertionResult AR
= HasChildCount(PC
, 1);
447 ::testing::AssertionResult AR
= HasTextAt(PC
, 0, Text
);
452 return ::testing::AssertionSuccess();
455 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
456 const CommandTraits
&Traits
,
458 VerbatimBlockComment
*&VBC
,
460 StringRef CloseName
) {
461 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, VBC
);
465 StringRef ActualName
= VBC
->getCommandName(Traits
);
466 if (ActualName
!= Name
)
467 return ::testing::AssertionFailure()
468 << "VerbatimBlockComment has name \"" << ActualName
.str() << "\", "
469 "expected \"" << Name
.str() << "\"";
471 StringRef ActualCloseName
= VBC
->getCloseName();
472 if (ActualCloseName
!= CloseName
)
473 return ::testing::AssertionFailure()
474 << "VerbatimBlockComment has closing command name \""
475 << ActualCloseName
.str() << "\", "
476 "expected \"" << CloseName
.str() << "\"";
478 return ::testing::AssertionSuccess();
484 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
485 const CommandTraits
&Traits
,
487 VerbatimBlockComment
*&VBC
,
491 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
496 if (VBC
->getNumLines() != 0)
497 return ::testing::AssertionFailure()
498 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
501 return ::testing::AssertionSuccess();
504 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
505 const CommandTraits
&Traits
,
507 VerbatimBlockComment
*&VBC
,
512 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
517 if (VBC
->getNumLines() != 1)
518 return ::testing::AssertionFailure()
519 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
522 StringRef ActualLine0
= VBC
->getText(0);
523 if (ActualLine0
!= Line0
)
524 return ::testing::AssertionFailure()
525 << "VerbatimBlockComment has lines[0] \"" << ActualLine0
.str() << "\", "
526 "expected \"" << Line0
.str() << "\"";
528 return ::testing::AssertionSuccess();
531 ::testing::AssertionResult
HasVerbatimBlockAt(const Comment
*C
,
532 const CommandTraits
&Traits
,
534 VerbatimBlockComment
*&VBC
,
540 ::testing::AssertionResult AR
= HasVerbatimBlockAt(C
, Traits
, Idx
, VBC
, Name
,
545 if (VBC
->getNumLines() != 2)
546 return ::testing::AssertionFailure()
547 << "VerbatimBlockComment has " << VBC
->getNumLines() << " lines(s), "
550 StringRef ActualLine0
= VBC
->getText(0);
551 if (ActualLine0
!= Line0
)
552 return ::testing::AssertionFailure()
553 << "VerbatimBlockComment has lines[0] \"" << ActualLine0
.str() << "\", "
554 "expected \"" << Line0
.str() << "\"";
556 StringRef ActualLine1
= VBC
->getText(1);
557 if (ActualLine1
!= Line1
)
558 return ::testing::AssertionFailure()
559 << "VerbatimBlockComment has lines[1] \"" << ActualLine1
.str() << "\", "
560 "expected \"" << Line1
.str() << "\"";
562 return ::testing::AssertionSuccess();
565 ::testing::AssertionResult
HasVerbatimLineAt(const Comment
*C
,
566 const CommandTraits
&Traits
,
568 VerbatimLineComment
*&VLC
,
571 ::testing::AssertionResult AR
= GetChildAt(C
, Idx
, VLC
);
575 StringRef ActualName
= VLC
->getCommandName(Traits
);
576 if (ActualName
!= Name
)
577 return ::testing::AssertionFailure()
578 << "VerbatimLineComment has name \"" << ActualName
.str() << "\", "
579 "expected \"" << Name
.str() << "\"";
581 StringRef ActualText
= VLC
->getText();
582 if (ActualText
!= Text
)
583 return ::testing::AssertionFailure()
584 << "VerbatimLineComment has text \"" << ActualText
.str() << "\", "
585 "expected \"" << Text
.str() << "\"";
587 return ::testing::AssertionSuccess();
591 TEST_F(CommentParserTest
, Basic1
) {
592 const char *Source
= "//";
594 FullComment
*FC
= parseString(Source
);
595 ASSERT_TRUE(HasChildCount(FC
, 0));
598 TEST_F(CommentParserTest
, Basic2
) {
599 const char *Source
= "// Meow";
601 FullComment
*FC
= parseString(Source
);
602 ASSERT_TRUE(HasChildCount(FC
, 1));
604 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " Meow"));
607 TEST_F(CommentParserTest
, Basic3
) {
612 FullComment
*FC
= parseString(Source
);
613 ASSERT_TRUE(HasChildCount(FC
, 1));
616 ParagraphComment
*PC
;
617 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
619 ASSERT_TRUE(HasChildCount(PC
, 2));
620 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 0, " Aaa"));
621 ASSERT_TRUE(HasTextAt(PC
, 1, " Bbb"));
625 TEST_F(CommentParserTest
, ParagraphSplitting1
) {
626 const char *Sources
[] = {
663 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
664 FullComment
*FC
= parseString(Sources
[i
]);
665 ASSERT_TRUE(HasChildCount(FC
, 2));
667 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " Aaa"));
668 ASSERT_TRUE(HasParagraphCommentAt(FC
, 1, " Bbb"));
672 TEST_F(CommentParserTest
, Paragraph1
) {
678 FullComment
*FC
= parseString(Source
);
679 ASSERT_TRUE(HasChildCount(FC
, 3));
681 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
683 BlockCommandComment
*BCC
;
684 ParagraphComment
*PC
;
685 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
687 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " Aaa"));
689 ASSERT_TRUE(HasParagraphCommentAt(FC
, 2, " Bbb"));
692 TEST_F(CommentParserTest
, Paragraph2
) {
693 const char *Source
= "// \\brief \\author";
695 FullComment
*FC
= parseString(Source
);
696 ASSERT_TRUE(HasChildCount(FC
, 3));
698 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
700 BlockCommandComment
*BCC
;
701 ParagraphComment
*PC
;
702 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
704 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " "));
707 BlockCommandComment
*BCC
;
708 ParagraphComment
*PC
;
709 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "author", PC
));
711 ASSERT_TRUE(GetChildAt(BCC
, 0, PC
));
712 ASSERT_TRUE(HasChildCount(PC
, 0));
716 TEST_F(CommentParserTest
, Paragraph3
) {
722 FullComment
*FC
= parseString(Source
);
723 ASSERT_TRUE(HasChildCount(FC
, 3));
725 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
727 BlockCommandComment
*BCC
;
728 ParagraphComment
*PC
;
729 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "brief", PC
));
731 ASSERT_TRUE(GetChildAt(BCC
, 0, PC
));
732 ASSERT_TRUE(HasChildCount(PC
, 2));
733 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 0, " Aaa"));
734 ASSERT_TRUE(HasTextAt(PC
, 1, " Bbb "));
737 BlockCommandComment
*BCC
;
738 ParagraphComment
*PC
;
739 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "author", PC
));
741 ASSERT_TRUE(HasParagraphCommentAt(BCC
, 0, " Ccc"));
745 TEST_F(CommentParserTest
, ParamCommand1
) {
746 const char *Source
= "// \\param aaa";
748 FullComment
*FC
= parseString(Source
);
749 ASSERT_TRUE(HasChildCount(FC
, 2));
751 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
753 ParamCommandComment
*PCC
;
754 ParagraphComment
*PC
;
755 ASSERT_TRUE(HasParamCommandAt(
756 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::In
,
757 /* IsDirectionExplicit = */ false, "aaa", PC
));
758 ASSERT_TRUE(HasChildCount(PCC
, 1));
759 ASSERT_TRUE(HasChildCount(PC
, 0));
763 TEST_F(CommentParserTest
, ParamCommand2
) {
764 const char *Source
= "// \\param\\brief";
766 FullComment
*FC
= parseString(Source
);
767 ASSERT_TRUE(HasChildCount(FC
, 3));
769 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
771 ParamCommandComment
*PCC
;
772 ParagraphComment
*PC
;
773 ASSERT_TRUE(HasParamCommandAt(FC
, Traits
, 1, PCC
, "param",
774 ParamCommandPassDirection::In
,
775 /* IsDirectionExplicit = */ false, "", PC
));
776 ASSERT_TRUE(HasChildCount(PCC
, 1));
777 ASSERT_TRUE(HasChildCount(PC
, 0));
780 BlockCommandComment
*BCC
;
781 ParagraphComment
*PC
;
782 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "brief", PC
));
783 ASSERT_TRUE(HasChildCount(PC
, 0));
787 TEST_F(CommentParserTest
, ParamCommand3
) {
788 const char *Sources
[] = {
789 "// \\param aaa Bbb\n",
798 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
799 FullComment
*FC
= parseString(Sources
[i
]);
800 ASSERT_TRUE(HasChildCount(FC
, 2));
802 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
804 ParamCommandComment
*PCC
;
805 ParagraphComment
*PC
;
806 ASSERT_TRUE(HasParamCommandAt(
807 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::In
,
808 /* IsDirectionExplicit = */ false, "aaa", PC
));
809 ASSERT_TRUE(HasChildCount(PCC
, 1));
810 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
815 TEST_F(CommentParserTest
, ParamCommand4
) {
816 const char *Sources
[] = {
817 "// \\param [in] aaa Bbb\n",
818 "// \\param[in] aaa Bbb\n",
820 "// [in] aaa Bbb\n"),
823 ("// \\param [in] aaa\n"
827 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
828 FullComment
*FC
= parseString(Sources
[i
]);
829 ASSERT_TRUE(HasChildCount(FC
, 2));
831 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
833 ParamCommandComment
*PCC
;
834 ParagraphComment
*PC
;
835 ASSERT_TRUE(HasParamCommandAt(
836 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::In
,
837 /* IsDirectionExplicit = */ true, "aaa", PC
));
838 ASSERT_TRUE(HasChildCount(PCC
, 1));
839 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
844 TEST_F(CommentParserTest
, ParamCommand5
) {
845 const char *Sources
[] = {
846 "// \\param [out] aaa Bbb\n",
847 "// \\param[out] aaa Bbb\n",
849 "// [out] aaa Bbb\n"),
850 ("// \\param [out]\n"
852 ("// \\param [out] aaa\n"
856 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
857 FullComment
*FC
= parseString(Sources
[i
]);
858 ASSERT_TRUE(HasChildCount(FC
, 2));
860 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
862 ParamCommandComment
*PCC
;
863 ParagraphComment
*PC
;
864 ASSERT_TRUE(HasParamCommandAt(
865 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::Out
,
866 /* IsDirectionExplicit = */ true, "aaa", PC
));
867 ASSERT_TRUE(HasChildCount(PCC
, 1));
868 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
873 TEST_F(CommentParserTest
, ParamCommand6
) {
874 const char *Sources
[] = {
875 "// \\param [in,out] aaa Bbb\n",
876 "// \\param[in,out] aaa Bbb\n",
877 "// \\param [in, out] aaa Bbb\n",
880 "// \\param [in,out]\n"
882 "// \\param [in,out] aaa\n"
886 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
887 FullComment
*FC
= parseString(Sources
[i
]);
888 ASSERT_TRUE(HasChildCount(FC
, 2));
890 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
892 ParamCommandComment
*PCC
;
893 ParagraphComment
*PC
;
894 ASSERT_TRUE(HasParamCommandAt(
895 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::InOut
,
896 /* IsDirectionExplicit = */ true, "aaa", PC
));
897 ASSERT_TRUE(HasChildCount(PCC
, 1));
898 ASSERT_TRUE(HasParagraphCommentAt(PCC
, 0, " Bbb"));
903 TEST_F(CommentParserTest
, ParamCommand7
) {
905 "// \\param aaa \\% Bbb \\$ ccc\n";
907 FullComment
*FC
= parseString(Source
);
908 ASSERT_TRUE(HasChildCount(FC
, 2));
910 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
912 ParamCommandComment
*PCC
;
913 ParagraphComment
*PC
;
914 ASSERT_TRUE(HasParamCommandAt(
915 FC
, Traits
, 1, PCC
, "param", ParamCommandPassDirection::In
,
916 /* IsDirectionExplicit = */ false, "aaa", PC
));
917 ASSERT_TRUE(HasChildCount(PCC
, 1));
919 ASSERT_TRUE(HasChildCount(PC
, 5));
920 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
921 ASSERT_TRUE(HasTextAt(PC
, 1, "%"));
922 ASSERT_TRUE(HasTextAt(PC
, 2, " Bbb "));
923 ASSERT_TRUE(HasTextAt(PC
, 3, "$"));
924 ASSERT_TRUE(HasTextAt(PC
, 4, " ccc"));
928 TEST_F(CommentParserTest
, TParamCommand1
) {
929 const char *Sources
[] = {
930 "// \\tparam aaa Bbb\n",
939 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
940 FullComment
*FC
= parseString(Sources
[i
]);
941 ASSERT_TRUE(HasChildCount(FC
, 2));
943 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
945 TParamCommandComment
*TPCC
;
946 ParagraphComment
*PC
;
947 ASSERT_TRUE(HasTParamCommandAt(FC
, Traits
, 1, TPCC
, "tparam",
949 ASSERT_TRUE(HasChildCount(TPCC
, 1));
950 ASSERT_TRUE(HasParagraphCommentAt(TPCC
, 0, " Bbb"));
955 TEST_F(CommentParserTest
, TParamCommand2
) {
956 const char *Source
= "// \\tparam\\brief";
958 FullComment
*FC
= parseString(Source
);
959 ASSERT_TRUE(HasChildCount(FC
, 3));
961 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
963 TParamCommandComment
*TPCC
;
964 ParagraphComment
*PC
;
965 ASSERT_TRUE(HasTParamCommandAt(FC
, Traits
, 1, TPCC
, "tparam", "", PC
));
966 ASSERT_TRUE(HasChildCount(TPCC
, 1));
967 ASSERT_TRUE(HasChildCount(PC
, 0));
970 BlockCommandComment
*BCC
;
971 ParagraphComment
*PC
;
972 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 2, BCC
, "brief", PC
));
973 ASSERT_TRUE(HasChildCount(PC
, 0));
978 TEST_F(CommentParserTest
, InlineCommand1
) {
979 const char *Source
= "// \\c";
981 FullComment
*FC
= parseString(Source
);
982 ASSERT_TRUE(HasChildCount(FC
, 1));
985 ParagraphComment
*PC
;
986 InlineCommandComment
*ICC
;
987 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
989 ASSERT_TRUE(HasChildCount(PC
, 2));
990 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
991 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", NoArgs()));
995 TEST_F(CommentParserTest
, InlineCommand2
) {
996 const char *Source
= "// \\c ";
998 FullComment
*FC
= parseString(Source
);
999 ASSERT_TRUE(HasChildCount(FC
, 1));
1002 ParagraphComment
*PC
;
1003 InlineCommandComment
*ICC
;
1004 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1006 ASSERT_TRUE(HasChildCount(PC
, 3));
1007 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1008 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", NoArgs()));
1009 ASSERT_TRUE(HasTextAt(PC
, 2, " "));
1013 TEST_F(CommentParserTest
, InlineCommand3
) {
1014 const char *Source
= "// \\c aaa\n";
1016 FullComment
*FC
= parseString(Source
);
1017 ASSERT_TRUE(HasChildCount(FC
, 1));
1020 ParagraphComment
*PC
;
1021 InlineCommandComment
*ICC
;
1022 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1024 ASSERT_TRUE(HasChildCount(PC
, 2));
1025 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1026 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", "aaa"));
1030 TEST_F(CommentParserTest
, InlineCommand4
) {
1031 const char *Source
= "// \\c aaa bbb";
1033 FullComment
*FC
= parseString(Source
);
1034 ASSERT_TRUE(HasChildCount(FC
, 1));
1037 ParagraphComment
*PC
;
1038 InlineCommandComment
*ICC
;
1039 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1041 ASSERT_TRUE(HasChildCount(PC
, 3));
1042 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1043 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "c", "aaa"));
1044 ASSERT_TRUE(HasTextAt(PC
, 2, " bbb"));
1048 TEST_F(CommentParserTest
, InlineCommand5
) {
1049 const char *Source
= "// \\unknown aaa\n";
1051 FullComment
*FC
= parseString(Source
);
1052 ASSERT_TRUE(HasChildCount(FC
, 1));
1055 ParagraphComment
*PC
;
1056 InlineCommandComment
*ICC
;
1057 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1059 ASSERT_TRUE(HasChildCount(PC
, 3));
1060 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1061 ASSERT_TRUE(HasInlineCommandAt(PC
, Traits
, 1, ICC
, "unknown", NoArgs()));
1062 ASSERT_TRUE(HasTextAt(PC
, 2, " aaa"));
1066 TEST_F(CommentParserTest
, HTML1
) {
1067 const char *Sources
[] = {
1073 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1074 FullComment
*FC
= parseString(Sources
[i
]);
1075 ASSERT_TRUE(HasChildCount(FC
, 1));
1078 ParagraphComment
*PC
;
1079 HTMLStartTagComment
*HST
;
1080 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1082 ASSERT_TRUE(HasChildCount(PC
, 2));
1083 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1084 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", NoAttrs()));
1089 TEST_F(CommentParserTest
, HTML2
) {
1090 const char *Sources
[] = {
1095 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1096 FullComment
*FC
= parseString(Sources
[i
]);
1097 ASSERT_TRUE(HasChildCount(FC
, 1));
1100 ParagraphComment
*PC
;
1101 HTMLStartTagComment
*HST
;
1102 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1104 ASSERT_TRUE(HasChildCount(PC
, 2));
1105 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1106 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "br", SelfClosing()));
1111 TEST_F(CommentParserTest
, HTML3
) {
1112 const char *Sources
[] = {
1119 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1120 FullComment
*FC
= parseString(Sources
[i
]);
1121 ASSERT_TRUE(HasChildCount(FC
, 1));
1124 ParagraphComment
*PC
;
1125 HTMLStartTagComment
*HST
;
1126 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1128 ASSERT_TRUE(HasChildCount(PC
, 2));
1129 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1130 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", "href", ""));
1135 TEST_F(CommentParserTest
, HTML4
) {
1136 const char *Sources
[] = {
1137 "// <a href=\"bbb\"",
1138 "// <a href=\"bbb\">",
1141 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1142 FullComment
*FC
= parseString(Sources
[i
]);
1143 ASSERT_TRUE(HasChildCount(FC
, 1));
1146 ParagraphComment
*PC
;
1147 HTMLStartTagComment
*HST
;
1148 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1150 ASSERT_TRUE(HasChildCount(PC
, 2));
1151 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1152 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "a", "href", "bbb"));
1157 TEST_F(CommentParserTest
, HTML5
) {
1158 const char *Sources
[] = {
1164 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1165 FullComment
*FC
= parseString(Sources
[i
]);
1166 ASSERT_TRUE(HasChildCount(FC
, 1));
1169 ParagraphComment
*PC
;
1170 HTMLEndTagComment
*HET
;
1171 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1173 ASSERT_TRUE(HasChildCount(PC
, 2));
1174 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1175 ASSERT_TRUE(HasHTMLEndTagAt(PC
, 1, HET
, "a"));
1180 TEST_F(CommentParserTest
, HTML6
) {
1181 const char *Source
=
1187 FullComment
*FC
= parseString(Source
);
1188 ASSERT_TRUE(HasChildCount(FC
, 1));
1191 ParagraphComment
*PC
;
1192 HTMLStartTagComment
*HST
;
1193 HTMLEndTagComment
*HET
;
1194 ASSERT_TRUE(GetChildAt(FC
, 0, PC
));
1196 ASSERT_TRUE(HasChildCount(PC
, 6));
1197 ASSERT_TRUE(HasTextAt(PC
, 0, " "));
1198 ASSERT_TRUE(HasHTMLStartTagAt(PC
, 1, HST
, "pre", NoAttrs()));
1199 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 2, " Aaa"));
1200 ASSERT_TRUE(HasTextWithNewlineAt(PC
, 3, " Bbb"));
1201 ASSERT_TRUE(HasTextAt(PC
, 4, " "));
1202 ASSERT_TRUE(HasHTMLEndTagAt(PC
, 5, HET
, "pre"));
1206 TEST_F(CommentParserTest
, VerbatimBlock1
) {
1207 const char *Source
= "// \\verbatim\\endverbatim\n";
1209 FullComment
*FC
= parseString(Source
);
1210 ASSERT_TRUE(HasChildCount(FC
, 2));
1212 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1214 VerbatimBlockComment
*VCC
;
1215 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VCC
,
1216 "verbatim", "endverbatim",
1221 TEST_F(CommentParserTest
, VerbatimBlock2
) {
1222 const char *Source
= "// \\verbatim Aaa \\endverbatim\n";
1224 FullComment
*FC
= parseString(Source
);
1225 ASSERT_TRUE(HasChildCount(FC
, 2));
1227 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1229 VerbatimBlockComment
*VBC
;
1230 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1231 "verbatim", "endverbatim",
1236 TEST_F(CommentParserTest
, VerbatimBlock3
) {
1237 const char *Source
= "// \\verbatim Aaa\n";
1239 FullComment
*FC
= parseString(Source
);
1240 ASSERT_TRUE(HasChildCount(FC
, 2));
1242 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1244 VerbatimBlockComment
*VBC
;
1245 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
, "verbatim", "",
1250 TEST_F(CommentParserTest
, VerbatimBlock4
) {
1251 const char *Source
=
1253 "//\\endverbatim\n";
1255 FullComment
*FC
= parseString(Source
);
1256 ASSERT_TRUE(HasChildCount(FC
, 1));
1259 VerbatimBlockComment
*VBC
;
1260 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 0, VBC
,
1261 "verbatim", "endverbatim",
1266 TEST_F(CommentParserTest
, VerbatimBlock5
) {
1267 const char *Sources
[] = {
1270 "//\\endverbatim\n",
1277 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1278 FullComment
*FC
= parseString(Sources
[i
]);
1279 ASSERT_TRUE(HasChildCount(FC
, 1));
1282 VerbatimBlockComment
*VBC
;
1283 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 0, VBC
,
1284 "verbatim", "endverbatim",
1290 TEST_F(CommentParserTest
, VerbatimBlock6
) {
1291 const char *Sources
[] = {
1294 "// \\endverbatim\n",
1298 " * \\endverbatim*/"
1301 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1302 FullComment
*FC
= parseString(Sources
[i
]);
1303 ASSERT_TRUE(HasChildCount(FC
, 2));
1305 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1307 VerbatimBlockComment
*VBC
;
1308 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1309 "verbatim", "endverbatim",
1315 TEST_F(CommentParserTest
, VerbatimBlock7
) {
1316 const char *Sources
[] = {
1320 "// \\endverbatim\n",
1325 " * \\endverbatim*/"
1328 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1329 FullComment
*FC
= parseString(Sources
[i
]);
1330 ASSERT_TRUE(HasChildCount(FC
, 2));
1332 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1334 VerbatimBlockComment
*VBC
;
1335 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1336 "verbatim", "endverbatim",
1337 Lines(), " Aaa", " Bbb"));
1342 TEST_F(CommentParserTest
, VerbatimBlock8
) {
1343 const char *Sources
[] = {
1348 "// \\endverbatim\n",
1354 " * \\endverbatim*/"
1356 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1357 FullComment
*FC
= parseString(Sources
[i
]);
1358 ASSERT_TRUE(HasChildCount(FC
, 2));
1360 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1362 VerbatimBlockComment
*VBC
;
1363 ASSERT_TRUE(HasVerbatimBlockAt(FC
, Traits
, 1, VBC
,
1364 "verbatim", "endverbatim"));
1365 ASSERT_EQ(3U, VBC
->getNumLines());
1366 ASSERT_EQ(" Aaa", VBC
->getText(0));
1367 ASSERT_EQ("", VBC
->getText(1));
1368 ASSERT_EQ(" Bbb", VBC
->getText(2));
1373 TEST_F(CommentParserTest
, VerbatimLine1
) {
1374 const char *Sources
[] = {
1379 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1380 FullComment
*FC
= parseString(Sources
[i
]);
1381 ASSERT_TRUE(HasChildCount(FC
, 2));
1383 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1385 VerbatimLineComment
*VLC
;
1386 ASSERT_TRUE(HasVerbatimLineAt(FC
, Traits
, 1, VLC
, "fn", ""));
1391 TEST_F(CommentParserTest
, VerbatimLine2
) {
1392 const char *Sources
[] = {
1393 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
1394 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
1397 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1398 FullComment
*FC
= parseString(Sources
[i
]);
1399 ASSERT_TRUE(HasChildCount(FC
, 2));
1401 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1403 VerbatimLineComment
*VLC
;
1404 ASSERT_TRUE(HasVerbatimLineAt(FC
, Traits
, 1, VLC
, "fn",
1405 " void *foo(const char *zzz = \"\\$\");"));
1410 TEST_F(CommentParserTest
, Deprecated
) {
1411 const char *Sources
[] = {
1412 "/** @deprecated*/",
1416 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1417 FullComment
*FC
= parseString(Sources
[i
]);
1418 ASSERT_TRUE(HasChildCount(FC
, 2));
1420 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1422 BlockCommandComment
*BCC
;
1423 ParagraphComment
*PC
;
1424 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "deprecated", PC
));
1425 ASSERT_TRUE(HasChildCount(PC
, 0));
1430 TEST_F(CommentParserTest
, ThrowsCommandHasArg1
) {
1431 const char *Sources
[] = {
1432 "/// @throws int This function throws an integer",
1434 "/// int This function throws an integer"),
1436 "/// int This function throws an integer"),
1439 "/// This function throws an integer"),
1442 "/// This function throws an integer"),
1445 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1446 FullComment
*FC
= parseString(Sources
[i
]);
1447 ASSERT_TRUE(HasChildCount(FC
, 2));
1449 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1451 BlockCommandComment
*BCC
;
1452 ParagraphComment
*PC
;
1453 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1454 ASSERT_TRUE(HasChildCount(PC
, 1));
1455 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1456 ASSERT_TRUE(BCC
->getArgText(0) == "int");
1461 TEST_F(CommentParserTest
, ThrowsCommandHasArg2
) {
1462 const char *Sources
[] = {
1463 "/// @throws int** This function throws a double pointer to an integer",
1466 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1467 FullComment
*FC
= parseString(Sources
[i
]);
1468 ASSERT_TRUE(HasChildCount(FC
, 2));
1470 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1472 BlockCommandComment
*BCC
;
1473 ParagraphComment
*PC
;
1474 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1475 ASSERT_TRUE(HasChildCount(PC
, 1));
1476 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1477 ASSERT_TRUE(BCC
->getArgText(0) == "int**");
1482 TEST_F(CommentParserTest
, ThrowsCommandHasArg3
) {
1483 const char *Sources
[] = {
1484 "/// @throws Error<T> error of type Error<T>",
1487 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1488 FullComment
*FC
= parseString(Sources
[i
]);
1489 ASSERT_TRUE(HasChildCount(FC
, 2));
1491 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1493 BlockCommandComment
*BCC
;
1494 ParagraphComment
*PC
;
1495 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1496 ASSERT_TRUE(HasChildCount(PC
, 3)); // Extra children because <T> is parsed
1497 // as a series of TextComments
1498 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1499 ASSERT_TRUE(BCC
->getArgText(0) == "Error<T>");
1504 TEST_F(CommentParserTest
, ThrowsCommandHasArg4
) {
1505 const char *Sources
[] = {
1506 "/// @throws Error<Container<T>> nested templates",
1509 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1510 FullComment
*FC
= parseString(Sources
[i
]);
1511 ASSERT_TRUE(HasChildCount(FC
, 2));
1513 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1515 BlockCommandComment
*BCC
;
1516 ParagraphComment
*PC
;
1517 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1518 ASSERT_TRUE(HasChildCount(PC
, 1));
1519 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1520 ASSERT_TRUE(BCC
->getArgText(0) == "Error<Container<T>>");
1525 TEST_F(CommentParserTest
, ThrowsCommandHasArg5
) {
1526 const char *Sources
[] = {
1527 "/// @throws Error<Ts...> variadic templates",
1530 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1531 FullComment
*FC
= parseString(Sources
[i
]);
1532 ASSERT_TRUE(HasChildCount(FC
, 2));
1534 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1536 BlockCommandComment
*BCC
;
1537 ParagraphComment
*PC
;
1538 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1539 ASSERT_TRUE(HasChildCount(PC
, 1));
1540 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1541 ASSERT_TRUE(BCC
->getArgText(0) == "Error<Ts...>");
1546 TEST_F(CommentParserTest
, ThrowsCommandHasArg6
) {
1547 const char *Sources
[] = {
1548 "/// @throws Foo<(1 > 0)> typo1",
1551 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1552 FullComment
*FC
= parseString(Sources
[i
]);
1553 ASSERT_TRUE(HasChildCount(FC
, 2));
1555 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1557 BlockCommandComment
*BCC
;
1558 ParagraphComment
*PC
;
1559 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1560 ASSERT_TRUE(HasChildCount(PC
, 1));
1561 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1562 ASSERT_TRUE(BCC
->getArgText(0) == "Foo<(1 >");
1567 // No matter the number of (unmatched) opening brackets, no type is parsed.
1568 TEST_F(CommentParserTest
, ThrowsCommandHasArg7
) {
1569 const char *Sources
[] = {
1571 "/// @throws Foo<<<",
1572 "/// @throws Foo<<<<<<<",
1573 "/// @throws Foo<\n",
1574 "/// @throws Foo<<<\n",
1575 "/// @throws Foo<<<<<<<\n",
1578 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1579 FullComment
*FC
= parseString(Sources
[i
]);
1580 ASSERT_TRUE(HasChildCount(FC
, 2));
1582 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1584 BlockCommandComment
*BCC
;
1585 ParagraphComment
*PC
;
1586 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1587 ASSERT_TRUE(HasChildCount(PC
, 0));
1588 ASSERT_TRUE(BCC
->getNumArgs() == 0);
1593 // Types with a non-matching closing bracket are parsed as if they are a type
1594 TEST_F(CommentParserTest
, ThrowsCommandHasArg8
) {
1595 const char *Sources
[] = {
1597 "/// @throws Foo>\n",
1600 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1601 FullComment
*FC
= parseString(Sources
[i
]);
1602 ASSERT_TRUE(HasChildCount(FC
, 2));
1604 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1606 BlockCommandComment
*BCC
;
1607 ParagraphComment
*PC
;
1608 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1609 ASSERT_TRUE(HasChildCount(PC
, 0));
1610 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1611 ASSERT_TRUE(BCC
->getArgText(0) == "Foo>");
1616 // Everying up until the end of the paragraph comment will be
1617 // eaten up if the template sequence is unterminated (i.e. number of
1618 // opening and closing brackets is not equal).
1619 TEST_F(CommentParserTest
, ThrowsCommandHasArg9
) {
1620 const char *Sources
[] = {
1621 "/// @throws Foo<Bar<t>\n"
1627 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1628 FullComment
*FC
= parseString(Sources
[i
]);
1629 ASSERT_TRUE(HasChildCount(FC
, 3));
1631 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1633 BlockCommandComment
*BCC
;
1634 ParagraphComment
*PC
;
1635 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "throws", PC
));
1636 ASSERT_TRUE(HasChildCount(PC
, 0));
1637 ASSERT_TRUE(BCC
->getNumArgs() == 0);
1642 TEST_F(CommentParserTest
, ParCommandHasArg1
) {
1643 const char *Sources
[] = {
1644 "/// @par Paragraph header:", "/// @par Paragraph header:\n",
1645 "/// @par Paragraph header:\r\n", "/// @par Paragraph header:\n\r",
1646 "/** @par Paragraph header:*/",
1649 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1650 FullComment
*FC
= parseString(Sources
[i
]);
1651 ASSERT_TRUE(HasChildCount(FC
, 2));
1653 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1655 BlockCommandComment
*BCC
;
1656 ParagraphComment
*PC
;
1657 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "par", PC
));
1658 ASSERT_TRUE(HasChildCount(PC
, 0));
1659 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1660 ASSERT_TRUE(BCC
->getArgText(0) == "Paragraph header:");
1665 TEST_F(CommentParserTest
, ParCommandHasArg2
) {
1666 const char *Sources
[] = {
1667 "/// @par Paragraph header: ", "/// @par Paragraph header: \n",
1668 "/// @par Paragraph header: \r\n", "/// @par Paragraph header: \n\r",
1669 "/** @par Paragraph header: */",
1672 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1673 FullComment
*FC
= parseString(Sources
[i
]);
1674 ASSERT_TRUE(HasChildCount(FC
, 2));
1676 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1678 BlockCommandComment
*BCC
;
1679 ParagraphComment
*PC
;
1680 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "par", PC
));
1681 ASSERT_TRUE(HasChildCount(PC
, 0));
1682 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1683 ASSERT_TRUE(BCC
->getArgText(0) == "Paragraph header: ");
1688 TEST_F(CommentParserTest
, ParCommandHasArg3
) {
1689 const char *Sources
[] = {
1690 ("/// @par Paragraph header:\n"
1691 "/// Paragraph body"),
1692 ("/// @par Paragraph header:\r\n"
1693 "/// Paragraph body"),
1694 ("/// @par Paragraph header:\n\r"
1695 "/// Paragraph body"),
1698 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1699 FullComment
*FC
= parseString(Sources
[i
]);
1700 ASSERT_TRUE(HasChildCount(FC
, 2));
1702 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1704 BlockCommandComment
*BCC
;
1705 ParagraphComment
*PC
;
1707 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "par", PC
));
1708 ASSERT_TRUE(HasChildCount(PC
, 1));
1709 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1710 ASSERT_TRUE(BCC
->getArgText(0) == "Paragraph header:");
1711 ASSERT_TRUE(GetChildAt(PC
, 0, TC
));
1712 ASSERT_TRUE(TC
->getText() == " Paragraph body");
1717 TEST_F(CommentParserTest
, ParCommandHasArg4
) {
1718 const char *Sources
[] = {
1719 ("/// @par Paragraph header:\n"
1720 "/// Paragraph body1\n"
1721 "/// Paragraph body2"),
1722 ("/// @par Paragraph header:\r\n"
1723 "/// Paragraph body1\n"
1724 "/// Paragraph body2"),
1725 ("/// @par Paragraph header:\n\r"
1726 "/// Paragraph body1\n"
1727 "/// Paragraph body2"),
1730 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1731 FullComment
*FC
= parseString(Sources
[i
]);
1732 ASSERT_TRUE(HasChildCount(FC
, 2));
1734 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1736 BlockCommandComment
*BCC
;
1737 ParagraphComment
*PC
;
1739 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "par", PC
));
1740 ASSERT_TRUE(HasChildCount(PC
, 2));
1741 ASSERT_TRUE(BCC
->getNumArgs() == 1);
1742 ASSERT_TRUE(BCC
->getArgText(0) == "Paragraph header:");
1743 ASSERT_TRUE(GetChildAt(PC
, 0, TC
));
1744 ASSERT_TRUE(TC
->getText() == " Paragraph body1");
1745 ASSERT_TRUE(GetChildAt(PC
, 1, TC
));
1746 ASSERT_TRUE(TC
->getText() == " Paragraph body2");
1751 TEST_F(CommentParserTest
, ParCommandHasArg5
) {
1752 const char *Sources
[] = {
1754 "/// Paragraphs with no text before newline have no heading"),
1756 "/// Paragraphs with no text before newline have no heading"),
1758 "/// Paragraphs with no text before newline have no heading"),
1761 for (size_t i
= 0, e
= std::size(Sources
); i
!= e
; i
++) {
1762 FullComment
*FC
= parseString(Sources
[i
]);
1763 ASSERT_TRUE(HasChildCount(FC
, 2));
1765 ASSERT_TRUE(HasParagraphCommentAt(FC
, 0, " "));
1767 BlockCommandComment
*BCC
;
1768 ParagraphComment
*PC
;
1770 ASSERT_TRUE(HasBlockCommandAt(FC
, Traits
, 1, BCC
, "par", PC
));
1771 ASSERT_TRUE(HasChildCount(PC
, 1));
1772 ASSERT_TRUE(BCC
->getNumArgs() == 0);
1773 ASSERT_TRUE(GetChildAt(PC
, 0, TC
));
1774 ASSERT_TRUE(TC
->getText() ==
1775 "Paragraphs with no text before newline have no heading");
1780 } // unnamed namespace
1782 } // end namespace comments
1783 } // end namespace clang