blob: d5dd0a9c56b14d8eae3fbeb29a18c0f4608fb01d [file] [log] [blame]
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +00001//===- unittests/AST/CommentParser.cpp ------ Comment parser tests --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/Basic/SourceManager.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Basic/Diagnostic.h"
13#include "clang/AST/Comment.h"
14#include "clang/AST/CommentLexer.h"
15#include "clang/AST/CommentParser.h"
16#include "clang/AST/CommentSema.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/Support/Allocator.h"
19#include <vector>
20
21#include "gtest/gtest.h"
22
23using namespace llvm;
24using namespace clang;
25
26namespace clang {
27namespace comments {
28
29namespace {
30
31const bool DEBUG = true;
32
33class CommentParserTest : public ::testing::Test {
34protected:
35 CommentParserTest()
36 : FileMgr(FileMgrOpts),
37 DiagID(new DiagnosticIDs()),
38 Diags(DiagID, new IgnoringDiagConsumer()),
39 SourceMgr(Diags, FileMgr) {
40 }
41
42 FileSystemOptions FileMgrOpts;
43 FileManager FileMgr;
44 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
45 DiagnosticsEngine Diags;
46 SourceManager SourceMgr;
47 llvm::BumpPtrAllocator Allocator;
48
49 FullComment *parseString(const char *Source);
50};
51
52FullComment *CommentParserTest::parseString(const char *Source) {
53 MemoryBuffer *Buf = MemoryBuffer::getMemBuffer(Source);
54 FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
55 SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
56
57 comments::Lexer L(Begin, CommentOptions(),
58 Source, Source + strlen(Source));
59
60 comments::Sema S(Allocator);
61 comments::Parser P(L, S, Allocator);
62 comments::FullComment *FC = P.parseFullComment();
63
64 if (DEBUG) {
65 llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n";
66 FC->dump(SourceMgr);
67 }
68
69 Token Tok;
70 L.lex(Tok);
71 if (Tok.is(tok::eof))
72 return FC;
73 else
74 return NULL;
75}
76
77::testing::AssertionResult HasChildCount(const Comment *C, size_t Count) {
78 if (!C)
79 return ::testing::AssertionFailure() << "Comment is NULL";
80
81 if (Count != C->child_count())
82 return ::testing::AssertionFailure()
83 << "Count = " << Count
84 << ", child_count = " << C->child_count();
85
86 return ::testing::AssertionSuccess();
87}
88
89template <typename T>
90::testing::AssertionResult GetChildAt(const Comment *C,
91 size_t Idx,
92 T *&Child) {
93 if (!C)
94 return ::testing::AssertionFailure() << "Comment is NULL";
95
96 if (Idx >= C->child_count())
97 return ::testing::AssertionFailure()
98 << "Idx out of range. Idx = " << Idx
99 << ", child_count = " << C->child_count();
100
101 Comment::child_iterator I = C->child_begin() + Idx;
102 Comment *CommentChild = *I;
103 if (!CommentChild)
104 return ::testing::AssertionFailure() << "Child is NULL";
105
106 Child = dyn_cast<T>(CommentChild);
107 if (!Child)
108 return ::testing::AssertionFailure()
109 << "Child is not of requested type, but a "
110 << CommentChild->getCommentKindName();
111
112 return ::testing::AssertionSuccess();
113}
114
115::testing::AssertionResult HasTextAt(const Comment *C,
116 size_t Idx,
117 StringRef Text) {
118 TextComment *TC;
119 ::testing::AssertionResult AR = GetChildAt(C, Idx, TC);
120 if (!AR)
121 return AR;
122
123 StringRef ActualText = TC->getText();
124 if (ActualText != Text)
125 return ::testing::AssertionFailure()
126 << "TextComment has text \"" << ActualText.str() << "\", "
127 "expected \"" << Text.str() << "\"";
128
129 if (TC->hasTrailingNewline())
130 return ::testing::AssertionFailure()
131 << "TextComment has a trailing newline";
132
133 return ::testing::AssertionSuccess();
134}
135
136::testing::AssertionResult HasTextWithNewlineAt(const Comment *C,
137 size_t Idx,
138 StringRef Text) {
139 TextComment *TC;
140 ::testing::AssertionResult AR = GetChildAt(C, Idx, TC);
141 if (!AR)
142 return AR;
143
144 StringRef ActualText = TC->getText();
145 if (ActualText != Text)
146 return ::testing::AssertionFailure()
147 << "TextComment has text \"" << ActualText.str() << "\", "
148 "expected \"" << Text.str() << "\"";
149
150 if (!TC->hasTrailingNewline())
151 return ::testing::AssertionFailure()
152 << "TextComment has no trailing newline";
153
154 return ::testing::AssertionSuccess();
155}
156
157::testing::AssertionResult HasBlockCommandAt(const Comment *C,
158 size_t Idx,
159 BlockCommandComment *&BCC,
160 StringRef Name,
161 ParagraphComment *&Paragraph) {
162 ::testing::AssertionResult AR = GetChildAt(C, Idx, BCC);
163 if (!AR)
164 return AR;
165
166 StringRef ActualName = BCC->getCommandName();
167 if (ActualName != Name)
168 return ::testing::AssertionFailure()
169 << "BlockCommandComment has name \"" << ActualName.str() << "\", "
170 "expected \"" << Name.str() << "\"";
171
172 Paragraph = BCC->getParagraph();
173
174 return ::testing::AssertionSuccess();
175}
176
177::testing::AssertionResult HasParamCommandAt(
178 const Comment *C,
179 size_t Idx,
180 ParamCommandComment *&PCC,
181 StringRef CommandName,
182 ParamCommandComment::PassDirection Direction,
183 bool IsDirectionExplicit,
184 StringRef ParamName,
185 ParagraphComment *&Paragraph) {
186 ::testing::AssertionResult AR = GetChildAt(C, Idx, PCC);
187 if (!AR)
188 return AR;
189
190 StringRef ActualCommandName = PCC->getCommandName();
191 if (ActualCommandName != CommandName)
192 return ::testing::AssertionFailure()
193 << "ParamCommandComment has name \"" << ActualCommandName.str() << "\", "
194 "expected \"" << CommandName.str() << "\"";
195
196 if (PCC->getDirection() != Direction)
197 return ::testing::AssertionFailure()
198 << "ParamCommandComment has direction " << PCC->getDirection() << ", "
199 "expected " << Direction;
200
201 if (PCC->isDirectionExplicit() != IsDirectionExplicit)
202 return ::testing::AssertionFailure()
203 << "ParamCommandComment has "
204 << (PCC->isDirectionExplicit() ? "explicit" : "implicit")
205 << " direction, "
206 "expected " << (IsDirectionExplicit ? "explicit" : "implicit");
207
208 StringRef ActualParamName = PCC->getParamName();
209 if (ActualParamName != ParamName)
210 return ::testing::AssertionFailure()
211 << "ParamCommandComment has name \"" << ActualParamName.str() << "\", "
212 "expected \"" << ParamName.str() << "\"";
213
214 Paragraph = PCC->getParagraph();
215
216 return ::testing::AssertionSuccess();
217}
218
219::testing::AssertionResult HasInlineCommandAt(const Comment *C,
220 size_t Idx,
221 InlineCommandComment *&ICC,
222 StringRef Name) {
223 ::testing::AssertionResult AR = GetChildAt(C, Idx, ICC);
224 if (!AR)
225 return AR;
226
227 StringRef ActualName = ICC->getCommandName();
228 if (ActualName != Name)
229 return ::testing::AssertionFailure()
230 << "InlineCommandComment has name \"" << ActualName.str() << "\", "
231 "expected \"" << Name.str() << "\"";
232
233 return ::testing::AssertionSuccess();
234}
235
236struct NoArgs {};
237
238::testing::AssertionResult HasInlineCommandAt(const Comment *C,
239 size_t Idx,
240 InlineCommandComment *&ICC,
241 StringRef Name,
242 NoArgs) {
243 ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name);
244 if (!AR)
245 return AR;
246
247 if (ICC->getArgCount() != 0)
248 return ::testing::AssertionFailure()
249 << "InlineCommandComment has " << ICC->getArgCount() << " arg(s), "
250 "expected 0";
251
252 return ::testing::AssertionSuccess();
253}
254
255::testing::AssertionResult HasInlineCommandAt(const Comment *C,
256 size_t Idx,
257 InlineCommandComment *&ICC,
258 StringRef Name,
259 StringRef Arg) {
260 ::testing::AssertionResult AR = HasInlineCommandAt(C, Idx, ICC, Name);
261 if (!AR)
262 return AR;
263
264 if (ICC->getArgCount() != 1)
265 return ::testing::AssertionFailure()
266 << "InlineCommandComment has " << ICC->getArgCount() << " arg(s), "
267 "expected 1";
268
269 StringRef ActualArg = ICC->getArgText(0);
270 if (ActualArg != Arg)
271 return ::testing::AssertionFailure()
272 << "InlineCommandComment has argument \"" << ActualArg.str() << "\", "
273 "expected \"" << Arg.str() << "\"";
274
275 return ::testing::AssertionSuccess();
276}
277
278::testing::AssertionResult HasHTMLOpenTagAt(const Comment *C,
279 size_t Idx,
280 HTMLOpenTagComment *&HOT,
281 StringRef TagName) {
282 ::testing::AssertionResult AR = GetChildAt(C, Idx, HOT);
283 if (!AR)
284 return AR;
285
286 StringRef ActualTagName = HOT->getTagName();
287 if (ActualTagName != TagName)
288 return ::testing::AssertionFailure()
289 << "HTMLOpenTagComment has name \"" << ActualTagName.str() << "\", "
290 "expected \"" << TagName.str() << "\"";
291
292 return ::testing::AssertionSuccess();
293}
294
295struct NoAttrs {};
296
297::testing::AssertionResult HasHTMLOpenTagAt(const Comment *C,
298 size_t Idx,
299 HTMLOpenTagComment *&HOT,
300 StringRef TagName,
301 NoAttrs) {
302 ::testing::AssertionResult AR = HasHTMLOpenTagAt(C, Idx, HOT, TagName);
303 if (!AR)
304 return AR;
305
306 if (HOT->getAttrCount() != 0)
307 return ::testing::AssertionFailure()
308 << "HTMLOpenTagComment has " << HOT->getAttrCount() << " attr(s), "
309 "expected 0";
310
311 return ::testing::AssertionSuccess();
312}
313
314::testing::AssertionResult HasHTMLOpenTagAt(const Comment *C,
315 size_t Idx,
316 HTMLOpenTagComment *&HOT,
317 StringRef TagName,
318 StringRef AttrName,
319 StringRef AttrValue) {
320 ::testing::AssertionResult AR = HasHTMLOpenTagAt(C, Idx, HOT, TagName);
321 if (!AR)
322 return AR;
323
324 if (HOT->getAttrCount() != 1)
325 return ::testing::AssertionFailure()
326 << "HTMLOpenTagComment has " << HOT->getAttrCount() << " attr(s), "
327 "expected 1";
328
329 StringRef ActualName = HOT->getAttr(0).Name;
330 if (ActualName != AttrName)
331 return ::testing::AssertionFailure()
332 << "HTMLOpenTagComment has attr \"" << ActualName.str() << "\", "
333 "expected \"" << AttrName.str() << "\"";
334
335 StringRef ActualValue = HOT->getAttr(0).Value;
336 if (ActualValue != AttrValue)
337 return ::testing::AssertionFailure()
338 << "HTMLOpenTagComment has attr value \"" << ActualValue.str() << "\", "
339 "expected \"" << AttrValue.str() << "\"";
340
341 return ::testing::AssertionSuccess();
342}
343
344::testing::AssertionResult HasHTMLCloseTagAt(const Comment *C,
345 size_t Idx,
346 HTMLCloseTagComment *&HCT,
347 StringRef TagName) {
348 ::testing::AssertionResult AR = GetChildAt(C, Idx, HCT);
349 if (!AR)
350 return AR;
351
352 StringRef ActualTagName = HCT->getTagName();
353 if (ActualTagName != TagName)
354 return ::testing::AssertionFailure()
355 << "HTMLCloseTagComment has name \"" << ActualTagName.str() << "\", "
356 "expected \"" << TagName.str() << "\"";
357
358 return ::testing::AssertionSuccess();
359}
360
361::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
362 size_t Idx,
363 VerbatimBlockComment *&VBC,
364 StringRef Name) {
365 ::testing::AssertionResult AR = GetChildAt(C, Idx, VBC);
366 if (!AR)
367 return AR;
368
369 StringRef ActualName = VBC->getCommandName();
370 if (ActualName != Name)
371 return ::testing::AssertionFailure()
372 << "VerbatimBlockComment has name \"" << ActualName.str() << "\", "
373 "expected \"" << Name.str() << "\"";
374
375 return ::testing::AssertionSuccess();
376}
377
378struct NoLines {};
379
380::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
381 size_t Idx,
382 VerbatimBlockComment *&VBC,
383 StringRef Name,
384 NoLines) {
385 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
386 if (!AR)
387 return AR;
388
389 if (VBC->getLineCount() != 0)
390 return ::testing::AssertionFailure()
391 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
392 "expected 0";
393
394 return ::testing::AssertionSuccess();
395}
396
397::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
398 size_t Idx,
399 VerbatimBlockComment *&VBC,
400 StringRef Name,
401 StringRef Line0) {
402 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
403 if (!AR)
404 return AR;
405
406 if (VBC->getLineCount() != 1)
407 return ::testing::AssertionFailure()
408 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
409 "expected 1";
410
411 StringRef ActualLine0 = VBC->getText(0);
412 if (ActualLine0 != Line0)
413 return ::testing::AssertionFailure()
414 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
415 "expected \"" << Line0.str() << "\"";
416
417 return ::testing::AssertionSuccess();
418}
419
420::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
421 size_t Idx,
422 VerbatimBlockComment *&VBC,
423 StringRef Name,
424 StringRef Line0,
425 StringRef Line1) {
426 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
427 if (!AR)
428 return AR;
429
430 if (VBC->getLineCount() != 2)
431 return ::testing::AssertionFailure()
432 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
433 "expected 2";
434
435 StringRef ActualLine0 = VBC->getText(0);
436 if (ActualLine0 != Line0)
437 return ::testing::AssertionFailure()
438 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
439 "expected \"" << Line0.str() << "\"";
440
441 StringRef ActualLine1 = VBC->getText(1);
442 if (ActualLine1 != Line1)
443 return ::testing::AssertionFailure()
444 << "VerbatimBlockComment has lines[1] \"" << ActualLine1.str() << "\", "
445 "expected \"" << Line1.str() << "\"";
446
447 return ::testing::AssertionSuccess();
448}
449
450::testing::AssertionResult HasVerbatimLineAt(const Comment *C,
451 size_t Idx,
452 VerbatimLineComment *&VLC,
453 StringRef Name,
454 StringRef Text) {
455 ::testing::AssertionResult AR = GetChildAt(C, Idx, VLC);
456 if (!AR)
457 return AR;
458
459 StringRef ActualName = VLC->getCommandName();
460 if (ActualName != Name)
461 return ::testing::AssertionFailure()
462 << "VerbatimLineComment has name \"" << ActualName.str() << "\", "
463 "expected \"" << Name.str() << "\"";
464
465 StringRef ActualText = VLC->getText();
466 if (ActualText != Text)
467 return ::testing::AssertionFailure()
468 << "VerbatimLineComment has text \"" << ActualText.str() << "\", "
469 "expected \"" << Text.str() << "\"";
470
471 return ::testing::AssertionSuccess();
472}
473
474
475TEST_F(CommentParserTest, Basic1) {
476 const char *Source = "//";
477
478 FullComment *FC = parseString(Source);
479 ASSERT_TRUE(HasChildCount(FC, 0));
480}
481
482TEST_F(CommentParserTest, Basic2) {
483 const char *Source = "// Meow";
484
485 FullComment *FC = parseString(Source);
486 ASSERT_TRUE(HasChildCount(FC, 1));
487
488 {
489 ParagraphComment *PC;
490 ASSERT_TRUE(GetChildAt(FC, 0, PC));
491
492 ASSERT_TRUE(HasChildCount(PC, 1));
493 ASSERT_TRUE(HasTextAt(PC, 0, " Meow"));
494 }
495}
496
497TEST_F(CommentParserTest, Basic3) {
498 const char *Source =
499 "// Aaa\n"
500 "// Bbb";
501
502 FullComment *FC = parseString(Source);
503 ASSERT_TRUE(HasChildCount(FC, 1));
504
505 {
506 ParagraphComment *PC;
507 ASSERT_TRUE(GetChildAt(FC, 0, PC));
508
509 ASSERT_TRUE(HasChildCount(PC, 2));
510 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa"));
511 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb"));
512 }
513}
514
515TEST_F(CommentParserTest, Paragraph1) {
516 const char *Sources[] = {
517 "// Aaa\n"
518 "//\n"
519 "// Bbb",
520
521 "// Aaa\n"
522 "//\n"
523 "//\n"
524 "// Bbb",
525 };
526
527
528 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
529 FullComment *FC = parseString(Sources[i]);
530 ASSERT_TRUE(HasChildCount(FC, 2));
531
532 {
533 ParagraphComment *PC;
534 ASSERT_TRUE(GetChildAt(FC, 0, PC));
535
536 ASSERT_TRUE(HasChildCount(PC, 1));
537 ASSERT_TRUE(HasTextAt(PC, 0, " Aaa"));
538 }
539 {
540 ParagraphComment *PC;
541 ASSERT_TRUE(GetChildAt(FC, 1, PC));
542
543 ASSERT_TRUE(HasChildCount(PC, 1));
544 ASSERT_TRUE(HasTextAt(PC, 0, " Bbb"));
545 }
546 }
547}
548
549TEST_F(CommentParserTest, Paragraph2) {
550 const char *Source =
551 "// \\brief Aaa\n"
552 "//\n"
553 "// Bbb";
554
555 FullComment *FC = parseString(Source);
556 ASSERT_TRUE(HasChildCount(FC, 3));
557
558 {
559 ParagraphComment *PC;
560 ASSERT_TRUE(GetChildAt(FC, 0, PC));
561
562 ASSERT_TRUE(HasChildCount(PC, 1));
563 ASSERT_TRUE(HasTextAt(PC, 0, " "));
564 }
565 {
566 BlockCommandComment *BCC;
567 ParagraphComment *PC;
568 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
569
570 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
571
572 ASSERT_TRUE(HasChildCount(PC, 1));
573 ASSERT_TRUE(HasTextAt(PC, 0, " Aaa"));
574 }
575 {
576 ParagraphComment *PC;
577 ASSERT_TRUE(GetChildAt(FC, 2, PC));
578
579 ASSERT_TRUE(HasChildCount(PC, 1));
580 ASSERT_TRUE(HasTextAt(PC, 0, " Bbb"));
581 }
582}
583
584TEST_F(CommentParserTest, Paragraph3) {
585 const char *Source = "// \\brief \\author";
586
587 FullComment *FC = parseString(Source);
588 ASSERT_TRUE(HasChildCount(FC, 3));
589
590 {
591 ParagraphComment *PC;
592 ASSERT_TRUE(GetChildAt(FC, 0, PC));
593
594 ASSERT_TRUE(HasChildCount(PC, 1));
595 ASSERT_TRUE(HasTextAt(PC, 0, " "));
596 }
597 {
598 BlockCommandComment *BCC;
599 ParagraphComment *PC;
600 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
601
602 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
603 ASSERT_TRUE(HasChildCount(PC, 1));
604 ASSERT_TRUE(HasTextAt(PC, 0, " "));
605 }
606 {
607 BlockCommandComment *BCC;
608 ParagraphComment *PC;
609 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
610
611 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
612 ASSERT_TRUE(HasChildCount(PC, 0));
613 }
614}
615
616TEST_F(CommentParserTest, Paragraph4) {
617 const char *Source =
618 "// \\brief Aaa\n"
619 "// Bbb \\author\n"
620 "// Ccc";
621
622 FullComment *FC = parseString(Source);
623 ASSERT_TRUE(HasChildCount(FC, 3));
624
625 {
626 ParagraphComment *PC;
627 ASSERT_TRUE(GetChildAt(FC, 0, PC));
628
629 ASSERT_TRUE(HasChildCount(PC, 1));
630 ASSERT_TRUE(HasTextAt(PC, 0, " "));
631 }
632 {
633 BlockCommandComment *BCC;
634 ParagraphComment *PC;
635 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
636
637 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
638 ASSERT_TRUE(HasChildCount(PC, 2));
639 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa"));
640 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb "));
641 }
642 {
643 BlockCommandComment *BCC;
644 ParagraphComment *PC;
645 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
646
647 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
648 ASSERT_TRUE(HasChildCount(PC, 1));
649 ASSERT_TRUE(HasTextAt(PC, 0, " Ccc"));
650 }
651}
652
653TEST_F(CommentParserTest, ParamCommand1) {
654 const char *Source =
655 "// \\param aaa\n"
656 "// \\param [in] aaa\n"
657 "// \\param [out] aaa\n"
658 "// \\param [in,out] aaa\n"
659 "// \\param [in, out] aaa\n";
660
661 FullComment *FC = parseString(Source);
662 ASSERT_TRUE(HasChildCount(FC, 6));
663
664 {
665 ParagraphComment *PC;
666 ASSERT_TRUE(GetChildAt(FC, 0, PC));
667
668 ASSERT_TRUE(HasChildCount(PC, 1));
669 ASSERT_TRUE(HasTextAt(PC, 0, " "));
670 }
671 {
672 ParamCommandComment *PCC;
673 ParagraphComment *PC;
674 ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
675 ParamCommandComment::In,
676 /* IsDirectionExplicit = */ false,
677 "aaa", PC));
678 ASSERT_TRUE(HasChildCount(PCC, 1));
679 ASSERT_TRUE(HasChildCount(PC, 1));
680 ASSERT_TRUE(HasTextAt(PC, 0, " "));
681 }
682 {
683 ParamCommandComment *PCC;
684 ParagraphComment *PC;
685 ASSERT_TRUE(HasParamCommandAt(FC, 2, PCC, "param",
686 ParamCommandComment::In,
687 /* IsDirectionExplicit = */ true,
688 "aaa", PC));
689 ASSERT_TRUE(HasChildCount(PCC, 1));
690 ASSERT_TRUE(HasChildCount(PC, 1));
691 ASSERT_TRUE(HasTextAt(PC, 0, " "));
692 }
693 {
694 ParamCommandComment *PCC;
695 ParagraphComment *PC;
696 ASSERT_TRUE(HasParamCommandAt(FC, 3, PCC, "param",
697 ParamCommandComment::Out,
698 /* IsDirectionExplicit = */ true,
699 "aaa", PC));
700 ASSERT_TRUE(HasChildCount(PCC, 1));
701 ASSERT_TRUE(HasChildCount(PC, 1));
702 ASSERT_TRUE(HasTextAt(PC, 0, " "));
703 }
704 {
705 ParamCommandComment *PCC;
706 ParagraphComment *PC;
707 ASSERT_TRUE(HasParamCommandAt(FC, 4, PCC, "param",
708 ParamCommandComment::InOut,
709 /* IsDirectionExplicit = */ true,
710 "aaa", PC));
711 ASSERT_TRUE(HasChildCount(PCC, 1));
712 ASSERT_TRUE(HasChildCount(PC, 1));
713 ASSERT_TRUE(HasTextAt(PC, 0, " "));
714 }
715 {
716 ParamCommandComment *PCC;
717 ParagraphComment *PC;
718 ASSERT_TRUE(HasParamCommandAt(FC, 5, PCC, "param",
719 ParamCommandComment::InOut,
720 /* IsDirectionExplicit = */ true,
721 "aaa", PC));
722 ASSERT_TRUE(HasChildCount(PCC, 1));
723 ASSERT_TRUE(HasChildCount(PC, 0));
724 }
725}
726
727TEST_F(CommentParserTest, InlineCommand1) {
728 const char *Source = "// \\c";
729
730 FullComment *FC = parseString(Source);
731 ASSERT_TRUE(HasChildCount(FC, 1));
732
733 {
734 ParagraphComment *PC;
735 InlineCommandComment *ICC;
736 ASSERT_TRUE(GetChildAt(FC, 0, PC));
737
738 ASSERT_TRUE(HasChildCount(PC, 2));
739 ASSERT_TRUE(HasTextAt(PC, 0, " "));
740 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
741 }
742}
743
744TEST_F(CommentParserTest, InlineCommand2) {
745 const char *Source = "// \\c ";
746
747 FullComment *FC = parseString(Source);
748 ASSERT_TRUE(HasChildCount(FC, 1));
749
750 {
751 ParagraphComment *PC;
752 InlineCommandComment *ICC;
753 ASSERT_TRUE(GetChildAt(FC, 0, PC));
754
755 ASSERT_TRUE(HasChildCount(PC, 3));
756 ASSERT_TRUE(HasTextAt(PC, 0, " "));
757 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
758 ASSERT_TRUE(HasTextAt(PC, 2, " "));
759 }
760}
761
762TEST_F(CommentParserTest, InlineCommand3) {
763 const char *Source = "// \\c aaa\n";
764
765 FullComment *FC = parseString(Source);
766 ASSERT_TRUE(HasChildCount(FC, 1));
767
768 {
769 ParagraphComment *PC;
770 InlineCommandComment *ICC;
771 ASSERT_TRUE(GetChildAt(FC, 0, PC));
772
773 ASSERT_TRUE(HasChildCount(PC, 2));
774 ASSERT_TRUE(HasTextAt(PC, 0, " "));
775 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
776 }
777}
778
779TEST_F(CommentParserTest, InlineCommand4) {
780 const char *Source = "// \\c aaa bbb";
781
782 FullComment *FC = parseString(Source);
783 ASSERT_TRUE(HasChildCount(FC, 1));
784
785 {
786 ParagraphComment *PC;
787 InlineCommandComment *ICC;
788 ASSERT_TRUE(GetChildAt(FC, 0, PC));
789
790 ASSERT_TRUE(HasChildCount(PC, 3));
791 ASSERT_TRUE(HasTextAt(PC, 0, " "));
792 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
793 ASSERT_TRUE(HasTextAt(PC, 2, " bbb"));
794 }
795}
796
797TEST_F(CommentParserTest, InlineCommand5) {
798 const char *Source = "// \\unknown aaa\n";
799
800 FullComment *FC = parseString(Source);
801 ASSERT_TRUE(HasChildCount(FC, 1));
802
803 {
804 ParagraphComment *PC;
805 InlineCommandComment *ICC;
806 ASSERT_TRUE(GetChildAt(FC, 0, PC));
807
808 ASSERT_TRUE(HasChildCount(PC, 3));
809 ASSERT_TRUE(HasTextAt(PC, 0, " "));
810 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "unknown", NoArgs()));
811 ASSERT_TRUE(HasTextAt(PC, 2, " aaa"));
812 }
813}
814
815TEST_F(CommentParserTest, HTML1) {
816 const char *Sources[] = {
817 "// <a",
818 "// <a>",
819 "// <a >"
820 };
821
822 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
823 FullComment *FC = parseString(Sources[i]);
824 ASSERT_TRUE(HasChildCount(FC, 1));
825
826 {
827 ParagraphComment *PC;
828 HTMLOpenTagComment *HOT;
829 ASSERT_TRUE(GetChildAt(FC, 0, PC));
830
831 ASSERT_TRUE(HasChildCount(PC, 2));
832 ASSERT_TRUE(HasTextAt(PC, 0, " "));
833 ASSERT_TRUE(HasHTMLOpenTagAt(PC, 1, HOT, "a", NoAttrs()));
834 }
835 }
836}
837
838TEST_F(CommentParserTest, HTML2) {
839 const char *Sources[] = {
840 "// <a href",
841 "// <a href ",
842 "// <a href>",
843 "// <a href >",
844 };
845
846 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
847 FullComment *FC = parseString(Sources[i]);
848 ASSERT_TRUE(HasChildCount(FC, 1));
849
850 {
851 ParagraphComment *PC;
852 HTMLOpenTagComment *HOT;
853 ASSERT_TRUE(GetChildAt(FC, 0, PC));
854
855 ASSERT_TRUE(HasChildCount(PC, 2));
856 ASSERT_TRUE(HasTextAt(PC, 0, " "));
857 ASSERT_TRUE(HasHTMLOpenTagAt(PC, 1, HOT, "a", "href", ""));
858 }
859 }
860}
861
862TEST_F(CommentParserTest, HTML3) {
863 const char *Sources[] = {
864 "// <a href=\"bbb\"",
865 "// <a href=\"bbb\">",
866 };
867
868 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
869 FullComment *FC = parseString(Sources[i]);
870 ASSERT_TRUE(HasChildCount(FC, 1));
871
872 {
873 ParagraphComment *PC;
874 HTMLOpenTagComment *HOT;
875 ASSERT_TRUE(GetChildAt(FC, 0, PC));
876
877 ASSERT_TRUE(HasChildCount(PC, 2));
878 ASSERT_TRUE(HasTextAt(PC, 0, " "));
879 ASSERT_TRUE(HasHTMLOpenTagAt(PC, 1, HOT, "a", "href", "bbb"));
880 }
881 }
882}
883
884TEST_F(CommentParserTest, HTML4) {
885 const char *Sources[] = {
886 "// </a",
887 "// </a>",
888 "// </a >"
889 };
890
891 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
892 FullComment *FC = parseString(Sources[i]);
893 ASSERT_TRUE(HasChildCount(FC, 1));
894
895 {
896 ParagraphComment *PC;
897 HTMLCloseTagComment *HCT;
898 ASSERT_TRUE(GetChildAt(FC, 0, PC));
899
900 ASSERT_TRUE(HasChildCount(PC, 2));
901 ASSERT_TRUE(HasTextAt(PC, 0, " "));
902 ASSERT_TRUE(HasHTMLCloseTagAt(PC, 1, HCT, "a"));
903 }
904 }
905}
906
907TEST_F(CommentParserTest, HTML5) {
908 const char *Source =
909 "// <pre>\n"
910 "// Aaa\n"
911 "// Bbb\n"
912 "// </pre>\n";
913
914 FullComment *FC = parseString(Source);
915 ASSERT_TRUE(HasChildCount(FC, 1));
916
917 {
918 ParagraphComment *PC;
919 HTMLOpenTagComment *HOT;
920 HTMLCloseTagComment *HCT;
921 ASSERT_TRUE(GetChildAt(FC, 0, PC));
922
923 ASSERT_TRUE(HasChildCount(PC, 6));
924 ASSERT_TRUE(HasTextAt(PC, 0, " "));
925 ASSERT_TRUE(HasHTMLOpenTagAt(PC, 1, HOT, "pre", NoAttrs()));
926 ASSERT_TRUE(HasTextWithNewlineAt(PC, 2, " Aaa"));
927 ASSERT_TRUE(HasTextWithNewlineAt(PC, 3, " Bbb"));
928 ASSERT_TRUE(HasTextAt(PC, 4, " "));
929 ASSERT_TRUE(HasHTMLCloseTagAt(PC, 5, HCT, "pre"));
930 }
931}
932
933TEST_F(CommentParserTest, VerbatimBlock1) {
934 const char *Source = "// \\verbatim\\endverbatim\n";
935
936 FullComment *FC = parseString(Source);
937 ASSERT_TRUE(HasChildCount(FC, 2));
938
939 {
940 ParagraphComment *PC;
941 ASSERT_TRUE(GetChildAt(FC, 0, PC));
942
943 ASSERT_TRUE(HasChildCount(PC, 1));
944 ASSERT_TRUE(HasTextAt(PC, 0, " "));
945 }
946 {
947 VerbatimBlockComment *VCC;
948 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VCC, "verbatim", NoLines()));
949 }
950}
951
952TEST_F(CommentParserTest, VerbatimBlock2) {
953 const char *Source = "// \\verbatim Aaa \\endverbatim\n";
954
955 FullComment *FC = parseString(Source);
956 ASSERT_TRUE(HasChildCount(FC, 2));
957
958 {
959 ParagraphComment *PC;
960 ASSERT_TRUE(GetChildAt(FC, 0, PC));
961
962 ASSERT_TRUE(HasChildCount(PC, 1));
963 ASSERT_TRUE(HasTextAt(PC, 0, " "));
964 }
965 {
966 VerbatimBlockComment *VBC;
967 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", " Aaa "));
968 }
969}
970
971TEST_F(CommentParserTest, VerbatimBlock3) {
972 const char *Source =
973 "//\\verbatim\n"
974 "//\\endverbatim\n";
975
976 FullComment *FC = parseString(Source);
977 ASSERT_TRUE(HasChildCount(FC, 1));
978
979 {
980 VerbatimBlockComment *VBC;
981 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", NoLines()));
982 }
983}
984
985TEST_F(CommentParserTest, VerbatimBlock4) {
986 const char *Sources[] = {
987 "//\\verbatim\n"
988 "// Aaa\n"
989 "//\\endverbatim\n",
990
991 "/*\\verbatim\n"
992 " * Aaa\n"
993 " *\\endverbatim*/"
994 };
995
996 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
997 FullComment *FC = parseString(Sources[i]);
998 ASSERT_TRUE(HasChildCount(FC, 1));
999
1000 {
1001 VerbatimBlockComment *VBC;
1002 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", " Aaa"));
1003 }
1004 }
1005}
1006
1007TEST_F(CommentParserTest, VerbatimBlock5) {
1008 const char *Sources[] = {
1009 "// \\verbatim\n"
1010 "// Aaa\n"
1011 "// \\endverbatim\n",
1012
1013 "/* \\verbatim\n"
1014 " * Aaa\n"
1015 " * \\endverbatim*/"
1016 };
1017
1018 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1019 FullComment *FC = parseString(Sources[i]);
1020 ASSERT_TRUE(HasChildCount(FC, 2));
1021
1022 {
1023 ParagraphComment *PC;
1024 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1025
1026 ASSERT_TRUE(HasChildCount(PC, 1));
1027 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1028 }
1029 {
1030 VerbatimBlockComment *VBC;
1031 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", " Aaa", " "));
1032 }
1033 }
1034}
1035
1036TEST_F(CommentParserTest, VerbatimBlock6) {
1037 const char *Sources[] = {
1038 "// \\verbatim\n"
1039 "// Aaa\n"
1040 "//\n"
1041 "// Bbb\n"
1042 "// \\endverbatim\n",
1043
1044 "/* \\verbatim\n"
1045 " * Aaa\n"
1046 " *\n"
1047 " * Bbb\n"
1048 " * \\endverbatim*/"
1049 };
1050 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1051 FullComment *FC = parseString(Sources[i]);
1052 ASSERT_TRUE(HasChildCount(FC, 2));
1053
1054 {
1055 ParagraphComment *PC;
1056 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1057
1058 ASSERT_TRUE(HasChildCount(PC, 1));
1059 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1060 }
1061 {
1062 VerbatimBlockComment *VBC;
1063 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim"));
1064 ASSERT_EQ(4U, VBC->getLineCount());
1065 ASSERT_EQ(" Aaa", VBC->getText(0));
1066 ASSERT_EQ("", VBC->getText(1));
1067 ASSERT_EQ(" Bbb", VBC->getText(2));
1068 ASSERT_EQ(" ", VBC->getText(3));
1069 }
1070 }
1071}
1072
1073TEST_F(CommentParserTest, VerbatimLine1) {
1074 const char *Sources[] = {
1075 "// \\fn",
1076 "// \\fn\n"
1077 };
1078
1079 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1080 FullComment *FC = parseString(Sources[i]);
1081 ASSERT_TRUE(HasChildCount(FC, 2));
1082
1083 {
1084 ParagraphComment *PC;
1085 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1086
1087 ASSERT_TRUE(HasChildCount(PC, 1));
1088 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1089 }
1090 {
1091 VerbatimLineComment *VLC;
1092 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", ""));
1093 }
1094 }
1095}
1096
1097TEST_F(CommentParserTest, VerbatimLine2) {
1098 const char *Sources[] = {
1099 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
1100 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
1101 };
1102
1103 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1104 FullComment *FC = parseString(Sources[i]);
1105 ASSERT_TRUE(HasChildCount(FC, 2));
1106
1107 {
1108 ParagraphComment *PC;
1109 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1110
1111 ASSERT_TRUE(HasChildCount(PC, 1));
1112 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1113 }
1114 {
1115 VerbatimLineComment *VLC;
1116 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn",
1117 " void *foo(const char *zzz = \"\\$\");"));
1118 }
1119 }
1120}
1121
1122} // unnamed namespace
1123
1124} // end namespace comments
1125} // end namespace clang
1126