1//===- unittests/AST/CommentParser.cpp ------ Comment parser tests --------===//
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
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"
22
23using namespace llvm;
24using namespace clang;
25
26namespace clang {
27namespace comments {
28
29namespace {
30
31const bool MY_DEBUG = true;
32
33class CommentParserTest : public ::testing::Test {
34protected:
35 CommentParserTest()
36 : FileMgr(FileMgrOpts),
37 DiagID(new DiagnosticIDs()),
38 Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
39 SourceMgr(Diags, FileMgr),
40 Traits(Allocator, CommentOptions()) {
41 }
42
43 FileSystemOptions FileMgrOpts;
44 FileManager FileMgr;
45 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
46 DiagnosticsEngine Diags;
47 SourceManager SourceMgr;
48 llvm::BumpPtrAllocator Allocator;
49 CommandTraits Traits;
50
51 FullComment *parseString(const char *Source);
52};
53
54FullComment *CommentParserTest::parseString(const char *Source) {
55 std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(InputData: Source);
56 FileID File = SourceMgr.createFileID(Buffer: std::move(Buf));
57 SourceLocation Begin = SourceMgr.getLocForStartOfFile(FID: File);
58
59 Lexer L(Allocator, Diags, Traits, Begin, Source, Source + strlen(Source));
60
61 Sema S(Allocator, SourceMgr, Diags, Traits, /*PP=*/ nullptr);
62 Parser P(L, S, Allocator, SourceMgr, Diags, Traits);
63 FullComment *FC = P.parseFullComment();
64
65 if (MY_DEBUG) {
66 llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n";
67 FC->dump();
68 }
69
70 Token Tok;
71 L.lex(T&: Tok);
72 if (Tok.is(K: tok::eof))
73 return FC;
74 else
75 return nullptr;
76}
77
78::testing::AssertionResult HasChildCount(const Comment *C, size_t Count) {
79 if (!C)
80 return ::testing::AssertionFailure() << "Comment is NULL";
81
82 if (Count != C->child_count())
83 return ::testing::AssertionFailure()
84 << "Count = " << Count
85 << ", child_count = " << C->child_count();
86
87 return ::testing::AssertionSuccess();
88}
89
90template <typename T>
91::testing::AssertionResult GetChildAt(const Comment *C,
92 size_t Idx,
93 T *&Child) {
94 if (!C)
95 return ::testing::AssertionFailure() << "Comment is NULL";
96
97 if (Idx >= C->child_count())
98 return ::testing::AssertionFailure()
99 << "Idx out of range. Idx = " << Idx
100 << ", child_count = " << C->child_count();
101
102 Comment::child_iterator I = C->child_begin() + Idx;
103 Comment *CommentChild = *I;
104 if (!CommentChild)
105 return ::testing::AssertionFailure() << "Child is NULL";
106
107 Child = dyn_cast<T>(CommentChild);
108 if (!Child)
109 return ::testing::AssertionFailure()
110 << "Child is not of requested type, but a "
111 << CommentChild->getCommentKindName();
112
113 return ::testing::AssertionSuccess();
114}
115
116::testing::AssertionResult HasTextAt(const Comment *C,
117 size_t Idx,
118 StringRef Text) {
119 TextComment *TC;
120 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: TC);
121 if (!AR)
122 return AR;
123
124 StringRef ActualText = TC->getText();
125 if (ActualText != Text)
126 return ::testing::AssertionFailure()
127 << "TextComment has text \"" << ActualText.str() << "\", "
128 "expected \"" << Text.str() << "\"";
129
130 if (TC->hasTrailingNewline())
131 return ::testing::AssertionFailure()
132 << "TextComment has a trailing newline";
133
134 return ::testing::AssertionSuccess();
135}
136
137::testing::AssertionResult HasTextWithNewlineAt(const Comment *C,
138 size_t Idx,
139 StringRef Text) {
140 TextComment *TC;
141 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: TC);
142 if (!AR)
143 return AR;
144
145 StringRef ActualText = TC->getText();
146 if (ActualText != Text)
147 return ::testing::AssertionFailure()
148 << "TextComment has text \"" << ActualText.str() << "\", "
149 "expected \"" << Text.str() << "\"";
150
151 if (!TC->hasTrailingNewline())
152 return ::testing::AssertionFailure()
153 << "TextComment has no trailing newline";
154
155 return ::testing::AssertionSuccess();
156}
157
158::testing::AssertionResult HasBlockCommandAt(const Comment *C,
159 const CommandTraits &Traits,
160 size_t Idx,
161 BlockCommandComment *&BCC,
162 StringRef Name,
163 ParagraphComment *&Paragraph) {
164 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: BCC);
165 if (!AR)
166 return AR;
167
168 StringRef ActualName = BCC->getCommandName(Traits);
169 if (ActualName != Name)
170 return ::testing::AssertionFailure()
171 << "BlockCommandComment has name \"" << ActualName.str() << "\", "
172 "expected \"" << Name.str() << "\"";
173
174 Paragraph = BCC->getParagraph();
175
176 return ::testing::AssertionSuccess();
177}
178
179::testing::AssertionResult
180HasParamCommandAt(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, Child&: PCC);
185 if (!AR)
186 return AR;
187
188 StringRef ActualCommandName = PCC->getCommandName(Traits);
189 if (ActualCommandName != CommandName)
190 return ::testing::AssertionFailure()
191 << "ParamCommandComment has name \"" << ActualCommandName.str() << "\", "
192 "expected \"" << CommandName.str() << "\"";
193
194 if (PCC->getDirection() != Direction)
195 return ::testing::AssertionFailure()
196 << "ParamCommandComment has direction "
197 << llvm::to_underlying(E: PCC->getDirection()) << ", expected "
198 << llvm::to_underlying(E: Direction);
199
200 if (PCC->isDirectionExplicit() != IsDirectionExplicit)
201 return ::testing::AssertionFailure()
202 << "ParamCommandComment has "
203 << (PCC->isDirectionExplicit() ? "explicit" : "implicit")
204 << " direction, "
205 "expected " << (IsDirectionExplicit ? "explicit" : "implicit");
206
207 if (!ParamName.empty() && !PCC->hasParamName())
208 return ::testing::AssertionFailure()
209 << "ParamCommandComment has no parameter name";
210
211 StringRef ActualParamName = PCC->hasParamName() ? PCC->getParamNameAsWritten() : "";
212 if (ActualParamName != ParamName)
213 return ::testing::AssertionFailure()
214 << "ParamCommandComment has parameter name \"" << ActualParamName.str()
215 << "\", "
216 "expected \"" << ParamName.str() << "\"";
217
218 Paragraph = PCC->getParagraph();
219
220 return ::testing::AssertionSuccess();
221}
222
223::testing::AssertionResult HasTParamCommandAt(
224 const Comment *C,
225 const CommandTraits &Traits,
226 size_t Idx,
227 TParamCommandComment *&TPCC,
228 StringRef CommandName,
229 StringRef ParamName,
230 ParagraphComment *&Paragraph) {
231 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: TPCC);
232 if (!AR)
233 return AR;
234
235 StringRef ActualCommandName = TPCC->getCommandName(Traits);
236 if (ActualCommandName != CommandName)
237 return ::testing::AssertionFailure()
238 << "TParamCommandComment has name \"" << ActualCommandName.str() << "\", "
239 "expected \"" << CommandName.str() << "\"";
240
241 if (!ParamName.empty() && !TPCC->hasParamName())
242 return ::testing::AssertionFailure()
243 << "TParamCommandComment has no parameter name";
244
245 StringRef ActualParamName = TPCC->hasParamName() ? TPCC->getParamNameAsWritten() : "";
246 if (ActualParamName != ParamName)
247 return ::testing::AssertionFailure()
248 << "TParamCommandComment has parameter name \"" << ActualParamName.str()
249 << "\", "
250 "expected \"" << ParamName.str() << "\"";
251
252 Paragraph = TPCC->getParagraph();
253
254 return ::testing::AssertionSuccess();
255}
256
257::testing::AssertionResult HasInlineCommandAt(const Comment *C,
258 const CommandTraits &Traits,
259 size_t Idx,
260 InlineCommandComment *&ICC,
261 StringRef Name) {
262 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: ICC);
263 if (!AR)
264 return AR;
265
266 StringRef ActualName = ICC->getCommandName(Traits);
267 if (ActualName != Name)
268 return ::testing::AssertionFailure()
269 << "InlineCommandComment has name \"" << ActualName.str() << "\", "
270 "expected \"" << Name.str() << "\"";
271
272 return ::testing::AssertionSuccess();
273}
274
275struct NoArgs {};
276
277::testing::AssertionResult HasInlineCommandAt(const Comment *C,
278 const CommandTraits &Traits,
279 size_t Idx,
280 InlineCommandComment *&ICC,
281 StringRef Name,
282 NoArgs) {
283 ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name);
284 if (!AR)
285 return AR;
286
287 if (ICC->getNumArgs() != 0)
288 return ::testing::AssertionFailure()
289 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), "
290 "expected 0";
291
292 return ::testing::AssertionSuccess();
293}
294
295::testing::AssertionResult HasInlineCommandAt(const Comment *C,
296 const CommandTraits &Traits,
297 size_t Idx,
298 InlineCommandComment *&ICC,
299 StringRef Name,
300 StringRef Arg) {
301 ::testing::AssertionResult AR = HasInlineCommandAt(C, Traits, Idx, ICC, Name);
302 if (!AR)
303 return AR;
304
305 if (ICC->getNumArgs() != 1)
306 return ::testing::AssertionFailure()
307 << "InlineCommandComment has " << ICC->getNumArgs() << " arg(s), "
308 "expected 1";
309
310 StringRef ActualArg = ICC->getArgText(Idx: 0);
311 if (ActualArg != Arg)
312 return ::testing::AssertionFailure()
313 << "InlineCommandComment has argument \"" << ActualArg.str() << "\", "
314 "expected \"" << Arg.str() << "\"";
315
316 return ::testing::AssertionSuccess();
317}
318
319::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
320 size_t Idx,
321 HTMLStartTagComment *&HST,
322 StringRef TagName) {
323 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: HST);
324 if (!AR)
325 return AR;
326
327 StringRef ActualTagName = HST->getTagName();
328 if (ActualTagName != TagName)
329 return ::testing::AssertionFailure()
330 << "HTMLStartTagComment has name \"" << ActualTagName.str() << "\", "
331 "expected \"" << TagName.str() << "\"";
332
333 return ::testing::AssertionSuccess();
334}
335
336struct SelfClosing {};
337
338::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
339 size_t Idx,
340 HTMLStartTagComment *&HST,
341 StringRef TagName,
342 SelfClosing) {
343 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
344 if (!AR)
345 return AR;
346
347 if (!HST->isSelfClosing())
348 return ::testing::AssertionFailure()
349 << "HTMLStartTagComment is not self-closing";
350
351 return ::testing::AssertionSuccess();
352}
353
354
355struct NoAttrs {};
356
357::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
358 size_t Idx,
359 HTMLStartTagComment *&HST,
360 StringRef TagName,
361 NoAttrs) {
362 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
363 if (!AR)
364 return AR;
365
366 if (HST->isSelfClosing())
367 return ::testing::AssertionFailure()
368 << "HTMLStartTagComment is self-closing";
369
370 if (HST->getNumAttrs() != 0)
371 return ::testing::AssertionFailure()
372 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), "
373 "expected 0";
374
375 return ::testing::AssertionSuccess();
376}
377
378::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
379 size_t Idx,
380 HTMLStartTagComment *&HST,
381 StringRef TagName,
382 StringRef AttrName,
383 StringRef AttrValue) {
384 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
385 if (!AR)
386 return AR;
387
388 if (HST->isSelfClosing())
389 return ::testing::AssertionFailure()
390 << "HTMLStartTagComment is self-closing";
391
392 if (HST->getNumAttrs() != 1)
393 return ::testing::AssertionFailure()
394 << "HTMLStartTagComment has " << HST->getNumAttrs() << " attr(s), "
395 "expected 1";
396
397 StringRef ActualName = HST->getAttr(Idx: 0).Name;
398 if (ActualName != AttrName)
399 return ::testing::AssertionFailure()
400 << "HTMLStartTagComment has attr \"" << ActualName.str() << "\", "
401 "expected \"" << AttrName.str() << "\"";
402
403 StringRef ActualValue = HST->getAttr(Idx: 0).Value;
404 if (ActualValue != AttrValue)
405 return ::testing::AssertionFailure()
406 << "HTMLStartTagComment has attr value \"" << ActualValue.str() << "\", "
407 "expected \"" << AttrValue.str() << "\"";
408
409 return ::testing::AssertionSuccess();
410}
411
412::testing::AssertionResult HasHTMLEndTagAt(const Comment *C,
413 size_t Idx,
414 HTMLEndTagComment *&HET,
415 StringRef TagName) {
416 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: HET);
417 if (!AR)
418 return AR;
419
420 StringRef ActualTagName = HET->getTagName();
421 if (ActualTagName != TagName)
422 return ::testing::AssertionFailure()
423 << "HTMLEndTagComment has name \"" << ActualTagName.str() << "\", "
424 "expected \"" << TagName.str() << "\"";
425
426 return ::testing::AssertionSuccess();
427}
428
429::testing::AssertionResult HasParagraphCommentAt(const Comment *C,
430 size_t Idx,
431 StringRef Text) {
432 ParagraphComment *PC;
433
434 {
435 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: PC);
436 if (!AR)
437 return AR;
438 }
439
440 {
441 ::testing::AssertionResult AR = HasChildCount(PC, 1);
442 if (!AR)
443 return AR;
444 }
445
446 {
447 ::testing::AssertionResult AR = HasTextAt(PC, 0, Text);
448 if (!AR)
449 return AR;
450 }
451
452 return ::testing::AssertionSuccess();
453}
454
455::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
456 const CommandTraits &Traits,
457 size_t Idx,
458 VerbatimBlockComment *&VBC,
459 StringRef Name,
460 StringRef CloseName) {
461 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: VBC);
462 if (!AR)
463 return AR;
464
465 StringRef ActualName = VBC->getCommandName(Traits);
466 if (ActualName != Name)
467 return ::testing::AssertionFailure()
468 << "VerbatimBlockComment has name \"" << ActualName.str() << "\", "
469 "expected \"" << Name.str() << "\"";
470
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() << "\"";
477
478 return ::testing::AssertionSuccess();
479}
480
481struct NoLines {};
482struct Lines {};
483
484::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
485 const CommandTraits &Traits,
486 size_t Idx,
487 VerbatimBlockComment *&VBC,
488 StringRef Name,
489 StringRef CloseName,
490 NoLines) {
491 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
492 CloseName);
493 if (!AR)
494 return AR;
495
496 if (VBC->getNumLines() != 0)
497 return ::testing::AssertionFailure()
498 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), "
499 "expected 0";
500
501 return ::testing::AssertionSuccess();
502}
503
504::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
505 const CommandTraits &Traits,
506 size_t Idx,
507 VerbatimBlockComment *&VBC,
508 StringRef Name,
509 StringRef CloseName,
510 Lines,
511 StringRef Line0) {
512 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
513 CloseName);
514 if (!AR)
515 return AR;
516
517 if (VBC->getNumLines() != 1)
518 return ::testing::AssertionFailure()
519 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), "
520 "expected 1";
521
522 StringRef ActualLine0 = VBC->getText(LineIdx: 0);
523 if (ActualLine0 != Line0)
524 return ::testing::AssertionFailure()
525 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
526 "expected \"" << Line0.str() << "\"";
527
528 return ::testing::AssertionSuccess();
529}
530
531::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
532 const CommandTraits &Traits,
533 size_t Idx,
534 VerbatimBlockComment *&VBC,
535 StringRef Name,
536 StringRef CloseName,
537 Lines,
538 StringRef Line0,
539 StringRef Line1) {
540 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Traits, Idx, VBC, Name,
541 CloseName);
542 if (!AR)
543 return AR;
544
545 if (VBC->getNumLines() != 2)
546 return ::testing::AssertionFailure()
547 << "VerbatimBlockComment has " << VBC->getNumLines() << " lines(s), "
548 "expected 2";
549
550 StringRef ActualLine0 = VBC->getText(LineIdx: 0);
551 if (ActualLine0 != Line0)
552 return ::testing::AssertionFailure()
553 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
554 "expected \"" << Line0.str() << "\"";
555
556 StringRef ActualLine1 = VBC->getText(LineIdx: 1);
557 if (ActualLine1 != Line1)
558 return ::testing::AssertionFailure()
559 << "VerbatimBlockComment has lines[1] \"" << ActualLine1.str() << "\", "
560 "expected \"" << Line1.str() << "\"";
561
562 return ::testing::AssertionSuccess();
563}
564
565::testing::AssertionResult HasVerbatimLineAt(const Comment *C,
566 const CommandTraits &Traits,
567 size_t Idx,
568 VerbatimLineComment *&VLC,
569 StringRef Name,
570 StringRef Text) {
571 ::testing::AssertionResult AR = GetChildAt(C, Idx, Child&: VLC);
572 if (!AR)
573 return AR;
574
575 StringRef ActualName = VLC->getCommandName(Traits);
576 if (ActualName != Name)
577 return ::testing::AssertionFailure()
578 << "VerbatimLineComment has name \"" << ActualName.str() << "\", "
579 "expected \"" << Name.str() << "\"";
580
581 StringRef ActualText = VLC->getText();
582 if (ActualText != Text)
583 return ::testing::AssertionFailure()
584 << "VerbatimLineComment has text \"" << ActualText.str() << "\", "
585 "expected \"" << Text.str() << "\"";
586
587 return ::testing::AssertionSuccess();
588}
589
590
591TEST_F(CommentParserTest, Basic1) {
592 const char *Source = "//";
593
594 FullComment *FC = parseString(Source);
595 ASSERT_TRUE(HasChildCount(FC, 0));
596}
597
598TEST_F(CommentParserTest, Basic2) {
599 const char *Source = "// Meow";
600
601 FullComment *FC = parseString(Source);
602 ASSERT_TRUE(HasChildCount(FC, 1));
603
604 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Meow"));
605}
606
607TEST_F(CommentParserTest, Basic3) {
608 const char *Source =
609 "// Aaa\n"
610 "// Bbb";
611
612 FullComment *FC = parseString(Source);
613 ASSERT_TRUE(HasChildCount(FC, 1));
614
615 {
616 ParagraphComment *PC;
617 ASSERT_TRUE(GetChildAt(FC, 0, PC));
618
619 ASSERT_TRUE(HasChildCount(PC, 2));
620 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa"));
621 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb"));
622 }
623}
624
625TEST_F(CommentParserTest, ParagraphSplitting1) {
626 const char *Sources[] = {
627 ("// Aaa\n"
628 "//\n"
629 "// Bbb"),
630
631 ("// Aaa\n"
632 "// \n"
633 "// Bbb"),
634
635 ("// Aaa\n"
636 "//\t\n"
637 "// Bbb"),
638
639 ("// Aaa\n"
640 "//\n"
641 "//\n"
642 "// Bbb"),
643
644 ("/**\n"
645 " Aaa\n"
646 "\n"
647 " Bbb\n"
648 "*/"),
649
650 ("/**\n"
651 " Aaa\n"
652 " \n"
653 " Bbb\n"
654 "*/"),
655
656 ("/**\n"
657 " Aaa\n"
658 "\t \n"
659 " Bbb\n"
660 "*/"),
661 };
662
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));
666
667 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " Aaa"));
668 ASSERT_TRUE(HasParagraphCommentAt(FC, 1, " Bbb"));
669 }
670}
671
672TEST_F(CommentParserTest, Paragraph1) {
673 const char *Source =
674 "// \\brief Aaa\n"
675 "//\n"
676 "// Bbb";
677
678 FullComment *FC = parseString(Source);
679 ASSERT_TRUE(HasChildCount(FC, 3));
680
681 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
682 {
683 BlockCommandComment *BCC;
684 ParagraphComment *PC;
685 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
686
687 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Aaa"));
688 }
689 ASSERT_TRUE(HasParagraphCommentAt(FC, 2, " Bbb"));
690}
691
692TEST_F(CommentParserTest, Paragraph2) {
693 const char *Source = "// \\brief \\author";
694
695 FullComment *FC = parseString(Source);
696 ASSERT_TRUE(HasChildCount(FC, 3));
697
698 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
699 {
700 BlockCommandComment *BCC;
701 ParagraphComment *PC;
702 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
703
704 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " "));
705 }
706 {
707 BlockCommandComment *BCC;
708 ParagraphComment *PC;
709 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC));
710
711 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
712 ASSERT_TRUE(HasChildCount(PC, 0));
713 }
714}
715
716TEST_F(CommentParserTest, Paragraph3) {
717 const char *Source =
718 "// \\brief Aaa\n"
719 "// Bbb \\author\n"
720 "// Ccc";
721
722 FullComment *FC = parseString(Source);
723 ASSERT_TRUE(HasChildCount(FC, 3));
724
725 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
726 {
727 BlockCommandComment *BCC;
728 ParagraphComment *PC;
729 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "brief", PC));
730
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 "));
735 }
736 {
737 BlockCommandComment *BCC;
738 ParagraphComment *PC;
739 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "author", PC));
740
741 ASSERT_TRUE(HasParagraphCommentAt(BCC, 0, " Ccc"));
742 }
743}
744
745TEST_F(CommentParserTest, ParamCommand1) {
746 const char *Source = "// \\param aaa";
747
748 FullComment *FC = parseString(Source);
749 ASSERT_TRUE(HasChildCount(FC, 2));
750
751 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
752 {
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));
760 }
761}
762
763TEST_F(CommentParserTest, ParamCommand2) {
764 const char *Source = "// \\param\\brief";
765
766 FullComment *FC = parseString(Source);
767 ASSERT_TRUE(HasChildCount(FC, 3));
768
769 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
770 {
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));
778 }
779 {
780 BlockCommandComment *BCC;
781 ParagraphComment *PC;
782 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC));
783 ASSERT_TRUE(HasChildCount(PC, 0));
784 }
785}
786
787TEST_F(CommentParserTest, ParamCommand3) {
788 const char *Sources[] = {
789 "// \\param aaa Bbb\n",
790 ("// \\param\n"
791 "// aaa Bbb\n"),
792 ("// \\param \n"
793 "// aaa Bbb\n"),
794 ("// \\param aaa\n"
795 "// Bbb\n")
796 };
797
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));
801
802 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
803 {
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"));
811 }
812 }
813}
814
815TEST_F(CommentParserTest, ParamCommand4) {
816 const char *Sources[] = {
817 "// \\param [in] aaa Bbb\n",
818 "// \\param[in] aaa Bbb\n",
819 ("// \\param\n"
820 "// [in] aaa Bbb\n"),
821 ("// \\param [in]\n"
822 "// aaa Bbb\n"),
823 ("// \\param [in] aaa\n"
824 "// Bbb\n"),
825 };
826
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));
830
831 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
832 {
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"));
840 }
841 }
842}
843
844TEST_F(CommentParserTest, ParamCommand5) {
845 const char *Sources[] = {
846 "// \\param [out] aaa Bbb\n",
847 "// \\param[out] aaa Bbb\n",
848 ("// \\param\n"
849 "// [out] aaa Bbb\n"),
850 ("// \\param [out]\n"
851 "// aaa Bbb\n"),
852 ("// \\param [out] aaa\n"
853 "// Bbb\n"),
854 };
855
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));
859
860 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
861 {
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"));
869 }
870 }
871}
872
873TEST_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",
878 "// \\param [in,\n"
879 "// out] aaa Bbb\n",
880 "// \\param [in,out]\n"
881 "// aaa Bbb\n",
882 "// \\param [in,out] aaa\n"
883 "// Bbb\n"
884 };
885
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));
889
890 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
891 {
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"));
899 }
900 }
901}
902
903TEST_F(CommentParserTest, ParamCommand7) {
904 const char *Source =
905 "// \\param aaa \\% Bbb \\$ ccc\n";
906
907 FullComment *FC = parseString(Source);
908 ASSERT_TRUE(HasChildCount(FC, 2));
909
910 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
911 {
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));
918
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"));
925 }
926}
927
928TEST_F(CommentParserTest, TParamCommand1) {
929 const char *Sources[] = {
930 "// \\tparam aaa Bbb\n",
931 "// \\tparam\n"
932 "// aaa Bbb\n",
933 "// \\tparam \n"
934 "// aaa Bbb\n",
935 "// \\tparam aaa\n"
936 "// Bbb\n"
937 };
938
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));
942
943 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
944 {
945 TParamCommandComment *TPCC;
946 ParagraphComment *PC;
947 ASSERT_TRUE(HasTParamCommandAt(FC, Traits, 1, TPCC, "tparam",
948 "aaa", PC));
949 ASSERT_TRUE(HasChildCount(TPCC, 1));
950 ASSERT_TRUE(HasParagraphCommentAt(TPCC, 0, " Bbb"));
951 }
952 }
953}
954
955TEST_F(CommentParserTest, TParamCommand2) {
956 const char *Source = "// \\tparam\\brief";
957
958 FullComment *FC = parseString(Source);
959 ASSERT_TRUE(HasChildCount(FC, 3));
960
961 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
962 {
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));
968 }
969 {
970 BlockCommandComment *BCC;
971 ParagraphComment *PC;
972 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 2, BCC, "brief", PC));
973 ASSERT_TRUE(HasChildCount(PC, 0));
974 }
975}
976
977
978TEST_F(CommentParserTest, InlineCommand1) {
979 const char *Source = "// \\c";
980
981 FullComment *FC = parseString(Source);
982 ASSERT_TRUE(HasChildCount(FC, 1));
983
984 {
985 ParagraphComment *PC;
986 InlineCommandComment *ICC;
987 ASSERT_TRUE(GetChildAt(FC, 0, PC));
988
989 ASSERT_TRUE(HasChildCount(PC, 2));
990 ASSERT_TRUE(HasTextAt(PC, 0, " "));
991 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", NoArgs()));
992 }
993}
994
995TEST_F(CommentParserTest, InlineCommand2) {
996 const char *Source = "// \\c ";
997
998 FullComment *FC = parseString(Source);
999 ASSERT_TRUE(HasChildCount(FC, 1));
1000
1001 {
1002 ParagraphComment *PC;
1003 InlineCommandComment *ICC;
1004 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1005
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, " "));
1010 }
1011}
1012
1013TEST_F(CommentParserTest, InlineCommand3) {
1014 const char *Source = "// \\c aaa\n";
1015
1016 FullComment *FC = parseString(Source);
1017 ASSERT_TRUE(HasChildCount(FC, 1));
1018
1019 {
1020 ParagraphComment *PC;
1021 InlineCommandComment *ICC;
1022 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1023
1024 ASSERT_TRUE(HasChildCount(PC, 2));
1025 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1026 ASSERT_TRUE(HasInlineCommandAt(PC, Traits, 1, ICC, "c", "aaa"));
1027 }
1028}
1029
1030TEST_F(CommentParserTest, InlineCommand4) {
1031 const char *Source = "// \\c aaa bbb";
1032
1033 FullComment *FC = parseString(Source);
1034 ASSERT_TRUE(HasChildCount(FC, 1));
1035
1036 {
1037 ParagraphComment *PC;
1038 InlineCommandComment *ICC;
1039 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1040
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"));
1045 }
1046}
1047
1048TEST_F(CommentParserTest, InlineCommand5) {
1049 const char *Source = "// \\unknown aaa\n";
1050
1051 FullComment *FC = parseString(Source);
1052 ASSERT_TRUE(HasChildCount(FC, 1));
1053
1054 {
1055 ParagraphComment *PC;
1056 InlineCommandComment *ICC;
1057 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1058
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"));
1063 }
1064}
1065
1066TEST_F(CommentParserTest, HTML1) {
1067 const char *Sources[] = {
1068 "// <a",
1069 "// <a>",
1070 "// <a >"
1071 };
1072
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));
1076
1077 {
1078 ParagraphComment *PC;
1079 HTMLStartTagComment *HST;
1080 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1081
1082 ASSERT_TRUE(HasChildCount(PC, 2));
1083 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1084 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", NoAttrs()));
1085 }
1086 }
1087}
1088
1089TEST_F(CommentParserTest, HTML2) {
1090 const char *Sources[] = {
1091 "// <br/>",
1092 "// <br />"
1093 };
1094
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));
1098
1099 {
1100 ParagraphComment *PC;
1101 HTMLStartTagComment *HST;
1102 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1103
1104 ASSERT_TRUE(HasChildCount(PC, 2));
1105 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1106 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "br", SelfClosing()));
1107 }
1108 }
1109}
1110
1111TEST_F(CommentParserTest, HTML3) {
1112 const char *Sources[] = {
1113 "// <a href",
1114 "// <a href ",
1115 "// <a href>",
1116 "// <a href >",
1117 };
1118
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));
1122
1123 {
1124 ParagraphComment *PC;
1125 HTMLStartTagComment *HST;
1126 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1127
1128 ASSERT_TRUE(HasChildCount(PC, 2));
1129 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1130 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", ""));
1131 }
1132 }
1133}
1134
1135TEST_F(CommentParserTest, HTML4) {
1136 const char *Sources[] = {
1137 "// <a href=\"bbb\"",
1138 "// <a href=\"bbb\">",
1139 };
1140
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));
1144
1145 {
1146 ParagraphComment *PC;
1147 HTMLStartTagComment *HST;
1148 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1149
1150 ASSERT_TRUE(HasChildCount(PC, 2));
1151 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1152 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "bbb"));
1153 }
1154 }
1155}
1156
1157TEST_F(CommentParserTest, HTML5) {
1158 const char *Sources[] = {
1159 "// </a",
1160 "// </a>",
1161 "// </a >"
1162 };
1163
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));
1167
1168 {
1169 ParagraphComment *PC;
1170 HTMLEndTagComment *HET;
1171 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1172
1173 ASSERT_TRUE(HasChildCount(PC, 2));
1174 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1175 ASSERT_TRUE(HasHTMLEndTagAt(PC, 1, HET, "a"));
1176 }
1177 }
1178}
1179
1180TEST_F(CommentParserTest, HTML6) {
1181 const char *Source =
1182 "// <pre>\n"
1183 "// Aaa\n"
1184 "// Bbb\n"
1185 "// </pre>\n";
1186
1187 FullComment *FC = parseString(Source);
1188 ASSERT_TRUE(HasChildCount(FC, 1));
1189
1190 {
1191 ParagraphComment *PC;
1192 HTMLStartTagComment *HST;
1193 HTMLEndTagComment *HET;
1194 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1195
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"));
1203 }
1204}
1205
1206TEST_F(CommentParserTest, VerbatimBlock1) {
1207 const char *Source = "// \\verbatim\\endverbatim\n";
1208
1209 FullComment *FC = parseString(Source);
1210 ASSERT_TRUE(HasChildCount(FC, 2));
1211
1212 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1213 {
1214 VerbatimBlockComment *VCC;
1215 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VCC,
1216 "verbatim", "endverbatim",
1217 NoLines()));
1218 }
1219}
1220
1221TEST_F(CommentParserTest, VerbatimBlock2) {
1222 const char *Source = "// \\verbatim Aaa \\endverbatim\n";
1223
1224 FullComment *FC = parseString(Source);
1225 ASSERT_TRUE(HasChildCount(FC, 2));
1226
1227 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1228 {
1229 VerbatimBlockComment *VBC;
1230 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
1231 "verbatim", "endverbatim",
1232 Lines(), " Aaa "));
1233 }
1234}
1235
1236TEST_F(CommentParserTest, VerbatimBlock3) {
1237 const char *Source = "// \\verbatim Aaa\n";
1238
1239 FullComment *FC = parseString(Source);
1240 ASSERT_TRUE(HasChildCount(FC, 2));
1241
1242 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1243 {
1244 VerbatimBlockComment *VBC;
1245 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC, "verbatim", "",
1246 Lines(), " Aaa"));
1247 }
1248}
1249
1250TEST_F(CommentParserTest, VerbatimBlock4) {
1251 const char *Source =
1252 "//\\verbatim\n"
1253 "//\\endverbatim\n";
1254
1255 FullComment *FC = parseString(Source);
1256 ASSERT_TRUE(HasChildCount(FC, 1));
1257
1258 {
1259 VerbatimBlockComment *VBC;
1260 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC,
1261 "verbatim", "endverbatim",
1262 NoLines()));
1263 }
1264}
1265
1266TEST_F(CommentParserTest, VerbatimBlock5) {
1267 const char *Sources[] = {
1268 "//\\verbatim\n"
1269 "// Aaa\n"
1270 "//\\endverbatim\n",
1271
1272 "/*\\verbatim\n"
1273 " * Aaa\n"
1274 " *\\endverbatim*/"
1275 };
1276
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));
1280
1281 {
1282 VerbatimBlockComment *VBC;
1283 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 0, VBC,
1284 "verbatim", "endverbatim",
1285 Lines(), " Aaa"));
1286 }
1287 }
1288}
1289
1290TEST_F(CommentParserTest, VerbatimBlock6) {
1291 const char *Sources[] = {
1292 "// \\verbatim\n"
1293 "// Aaa\n"
1294 "// \\endverbatim\n",
1295
1296 "/* \\verbatim\n"
1297 " * Aaa\n"
1298 " * \\endverbatim*/"
1299 };
1300
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));
1304
1305 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1306 {
1307 VerbatimBlockComment *VBC;
1308 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
1309 "verbatim", "endverbatim",
1310 Lines(), " Aaa"));
1311 }
1312 }
1313}
1314
1315TEST_F(CommentParserTest, VerbatimBlock7) {
1316 const char *Sources[] = {
1317 "// \\verbatim\n"
1318 "// Aaa\n"
1319 "// Bbb\n"
1320 "// \\endverbatim\n",
1321
1322 "/* \\verbatim\n"
1323 " * Aaa\n"
1324 " * Bbb\n"
1325 " * \\endverbatim*/"
1326 };
1327
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));
1331
1332 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1333 {
1334 VerbatimBlockComment *VBC;
1335 ASSERT_TRUE(HasVerbatimBlockAt(FC, Traits, 1, VBC,
1336 "verbatim", "endverbatim",
1337 Lines(), " Aaa", " Bbb"));
1338 }
1339 }
1340}
1341
1342TEST_F(CommentParserTest, VerbatimBlock8) {
1343 const char *Sources[] = {
1344 "// \\verbatim\n"
1345 "// Aaa\n"
1346 "//\n"
1347 "// Bbb\n"
1348 "// \\endverbatim\n",
1349
1350 "/* \\verbatim\n"
1351 " * Aaa\n"
1352 " *\n"
1353 " * Bbb\n"
1354 " * \\endverbatim*/"
1355 };
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));
1359
1360 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1361 {
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));
1369 }
1370 }
1371}
1372
1373TEST_F(CommentParserTest, VerbatimLine1) {
1374 const char *Sources[] = {
1375 "// \\fn",
1376 "// \\fn\n"
1377 };
1378
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));
1382
1383 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1384 {
1385 VerbatimLineComment *VLC;
1386 ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn", ""));
1387 }
1388 }
1389}
1390
1391TEST_F(CommentParserTest, VerbatimLine2) {
1392 const char *Sources[] = {
1393 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
1394 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
1395 };
1396
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));
1400
1401 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1402 {
1403 VerbatimLineComment *VLC;
1404 ASSERT_TRUE(HasVerbatimLineAt(FC, Traits, 1, VLC, "fn",
1405 " void *foo(const char *zzz = \"\\$\");"));
1406 }
1407 }
1408}
1409
1410TEST_F(CommentParserTest, Deprecated) {
1411 const char *Sources[] = {
1412 "/** @deprecated*/",
1413 "/// @deprecated\n"
1414 };
1415
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));
1419
1420 ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
1421 {
1422 BlockCommandComment *BCC;
1423 ParagraphComment *PC;
1424 ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "deprecated", PC));
1425 ASSERT_TRUE(HasChildCount(PC, 0));
1426 }
1427 }
1428}
1429
1430} // unnamed namespace
1431
1432} // end namespace comments
1433} // end namespace clang
1434
1435

source code of clang/unittests/AST/CommentParser.cpp