blob: d2f87488ded2613476d60001a1daab96f64f18f5 [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
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +000060 comments::Sema S(Allocator, SourceMgr, Diags);
61 comments::Parser P(L, S, Allocator, SourceMgr, Diags);
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +000062 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
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000278::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
279 size_t Idx,
280 HTMLStartTagComment *&HST,
281 StringRef TagName) {
282 ::testing::AssertionResult AR = GetChildAt(C, Idx, HST);
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000283 if (!AR)
284 return AR;
285
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000286 StringRef ActualTagName = HST->getTagName();
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000287 if (ActualTagName != TagName)
288 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000289 << "HTMLStartTagComment has name \"" << ActualTagName.str() << "\", "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000290 "expected \"" << TagName.str() << "\"";
291
292 return ::testing::AssertionSuccess();
293}
294
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000295struct SelfClosing {};
296
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000297::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
298 size_t Idx,
299 HTMLStartTagComment *&HST,
300 StringRef TagName,
301 SelfClosing) {
302 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000303 if (!AR)
304 return AR;
305
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000306 if (!HST->isSelfClosing())
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000307 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000308 << "HTMLStartTagComment is not self-closing";
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000309
310 return ::testing::AssertionSuccess();
311}
312
313
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000314struct NoAttrs {};
315
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000316::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
317 size_t Idx,
318 HTMLStartTagComment *&HST,
319 StringRef TagName,
320 NoAttrs) {
321 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000322 if (!AR)
323 return AR;
324
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000325 if (HST->isSelfClosing())
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000326 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000327 << "HTMLStartTagComment is self-closing";
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000328
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000329 if (HST->getAttrCount() != 0)
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000330 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000331 << "HTMLStartTagComment has " << HST->getAttrCount() << " attr(s), "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000332 "expected 0";
333
334 return ::testing::AssertionSuccess();
335}
336
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000337::testing::AssertionResult HasHTMLStartTagAt(const Comment *C,
338 size_t Idx,
339 HTMLStartTagComment *&HST,
340 StringRef TagName,
341 StringRef AttrName,
342 StringRef AttrValue) {
343 ::testing::AssertionResult AR = HasHTMLStartTagAt(C, Idx, HST, TagName);
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000344 if (!AR)
345 return AR;
346
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000347 if (HST->isSelfClosing())
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000348 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000349 << "HTMLStartTagComment is self-closing";
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000350
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000351 if (HST->getAttrCount() != 1)
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000352 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000353 << "HTMLStartTagComment has " << HST->getAttrCount() << " attr(s), "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000354 "expected 1";
355
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000356 StringRef ActualName = HST->getAttr(0).Name;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000357 if (ActualName != AttrName)
358 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000359 << "HTMLStartTagComment has attr \"" << ActualName.str() << "\", "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000360 "expected \"" << AttrName.str() << "\"";
361
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000362 StringRef ActualValue = HST->getAttr(0).Value;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000363 if (ActualValue != AttrValue)
364 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000365 << "HTMLStartTagComment has attr value \"" << ActualValue.str() << "\", "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000366 "expected \"" << AttrValue.str() << "\"";
367
368 return ::testing::AssertionSuccess();
369}
370
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000371::testing::AssertionResult HasHTMLEndTagAt(const Comment *C,
372 size_t Idx,
373 HTMLEndTagComment *&HET,
374 StringRef TagName) {
375 ::testing::AssertionResult AR = GetChildAt(C, Idx, HET);
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000376 if (!AR)
377 return AR;
378
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000379 StringRef ActualTagName = HET->getTagName();
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000380 if (ActualTagName != TagName)
381 return ::testing::AssertionFailure()
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000382 << "HTMLEndTagComment has name \"" << ActualTagName.str() << "\", "
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000383 "expected \"" << TagName.str() << "\"";
384
385 return ::testing::AssertionSuccess();
386}
387
388::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
389 size_t Idx,
390 VerbatimBlockComment *&VBC,
391 StringRef Name) {
392 ::testing::AssertionResult AR = GetChildAt(C, Idx, VBC);
393 if (!AR)
394 return AR;
395
396 StringRef ActualName = VBC->getCommandName();
397 if (ActualName != Name)
398 return ::testing::AssertionFailure()
399 << "VerbatimBlockComment has name \"" << ActualName.str() << "\", "
400 "expected \"" << Name.str() << "\"";
401
402 return ::testing::AssertionSuccess();
403}
404
405struct NoLines {};
406
407::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
408 size_t Idx,
409 VerbatimBlockComment *&VBC,
410 StringRef Name,
411 NoLines) {
412 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
413 if (!AR)
414 return AR;
415
416 if (VBC->getLineCount() != 0)
417 return ::testing::AssertionFailure()
418 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
419 "expected 0";
420
421 return ::testing::AssertionSuccess();
422}
423
424::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
425 size_t Idx,
426 VerbatimBlockComment *&VBC,
427 StringRef Name,
428 StringRef Line0) {
429 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
430 if (!AR)
431 return AR;
432
433 if (VBC->getLineCount() != 1)
434 return ::testing::AssertionFailure()
435 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
436 "expected 1";
437
438 StringRef ActualLine0 = VBC->getText(0);
439 if (ActualLine0 != Line0)
440 return ::testing::AssertionFailure()
441 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
442 "expected \"" << Line0.str() << "\"";
443
444 return ::testing::AssertionSuccess();
445}
446
447::testing::AssertionResult HasVerbatimBlockAt(const Comment *C,
448 size_t Idx,
449 VerbatimBlockComment *&VBC,
450 StringRef Name,
451 StringRef Line0,
452 StringRef Line1) {
453 ::testing::AssertionResult AR = HasVerbatimBlockAt(C, Idx, VBC, Name);
454 if (!AR)
455 return AR;
456
457 if (VBC->getLineCount() != 2)
458 return ::testing::AssertionFailure()
459 << "VerbatimBlockComment has " << VBC->getLineCount() << " lines(s), "
460 "expected 2";
461
462 StringRef ActualLine0 = VBC->getText(0);
463 if (ActualLine0 != Line0)
464 return ::testing::AssertionFailure()
465 << "VerbatimBlockComment has lines[0] \"" << ActualLine0.str() << "\", "
466 "expected \"" << Line0.str() << "\"";
467
468 StringRef ActualLine1 = VBC->getText(1);
469 if (ActualLine1 != Line1)
470 return ::testing::AssertionFailure()
471 << "VerbatimBlockComment has lines[1] \"" << ActualLine1.str() << "\", "
472 "expected \"" << Line1.str() << "\"";
473
474 return ::testing::AssertionSuccess();
475}
476
477::testing::AssertionResult HasVerbatimLineAt(const Comment *C,
478 size_t Idx,
479 VerbatimLineComment *&VLC,
480 StringRef Name,
481 StringRef Text) {
482 ::testing::AssertionResult AR = GetChildAt(C, Idx, VLC);
483 if (!AR)
484 return AR;
485
486 StringRef ActualName = VLC->getCommandName();
487 if (ActualName != Name)
488 return ::testing::AssertionFailure()
489 << "VerbatimLineComment has name \"" << ActualName.str() << "\", "
490 "expected \"" << Name.str() << "\"";
491
492 StringRef ActualText = VLC->getText();
493 if (ActualText != Text)
494 return ::testing::AssertionFailure()
495 << "VerbatimLineComment has text \"" << ActualText.str() << "\", "
496 "expected \"" << Text.str() << "\"";
497
498 return ::testing::AssertionSuccess();
499}
500
501
502TEST_F(CommentParserTest, Basic1) {
503 const char *Source = "//";
504
505 FullComment *FC = parseString(Source);
506 ASSERT_TRUE(HasChildCount(FC, 0));
507}
508
509TEST_F(CommentParserTest, Basic2) {
510 const char *Source = "// Meow";
511
512 FullComment *FC = parseString(Source);
513 ASSERT_TRUE(HasChildCount(FC, 1));
514
515 {
516 ParagraphComment *PC;
517 ASSERT_TRUE(GetChildAt(FC, 0, PC));
518
519 ASSERT_TRUE(HasChildCount(PC, 1));
520 ASSERT_TRUE(HasTextAt(PC, 0, " Meow"));
521 }
522}
523
524TEST_F(CommentParserTest, Basic3) {
525 const char *Source =
526 "// Aaa\n"
527 "// Bbb";
528
529 FullComment *FC = parseString(Source);
530 ASSERT_TRUE(HasChildCount(FC, 1));
531
532 {
533 ParagraphComment *PC;
534 ASSERT_TRUE(GetChildAt(FC, 0, PC));
535
536 ASSERT_TRUE(HasChildCount(PC, 2));
537 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa"));
538 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb"));
539 }
540}
541
542TEST_F(CommentParserTest, Paragraph1) {
543 const char *Sources[] = {
544 "// Aaa\n"
545 "//\n"
546 "// Bbb",
547
548 "// Aaa\n"
549 "//\n"
550 "//\n"
551 "// Bbb",
552 };
553
554
555 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
556 FullComment *FC = parseString(Sources[i]);
557 ASSERT_TRUE(HasChildCount(FC, 2));
558
559 {
560 ParagraphComment *PC;
561 ASSERT_TRUE(GetChildAt(FC, 0, PC));
562
563 ASSERT_TRUE(HasChildCount(PC, 1));
564 ASSERT_TRUE(HasTextAt(PC, 0, " Aaa"));
565 }
566 {
567 ParagraphComment *PC;
568 ASSERT_TRUE(GetChildAt(FC, 1, PC));
569
570 ASSERT_TRUE(HasChildCount(PC, 1));
571 ASSERT_TRUE(HasTextAt(PC, 0, " Bbb"));
572 }
573 }
574}
575
576TEST_F(CommentParserTest, Paragraph2) {
577 const char *Source =
578 "// \\brief Aaa\n"
579 "//\n"
580 "// Bbb";
581
582 FullComment *FC = parseString(Source);
583 ASSERT_TRUE(HasChildCount(FC, 3));
584
585 {
586 ParagraphComment *PC;
587 ASSERT_TRUE(GetChildAt(FC, 0, PC));
588
589 ASSERT_TRUE(HasChildCount(PC, 1));
590 ASSERT_TRUE(HasTextAt(PC, 0, " "));
591 }
592 {
593 BlockCommandComment *BCC;
594 ParagraphComment *PC;
595 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
596
597 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
598
599 ASSERT_TRUE(HasChildCount(PC, 1));
600 ASSERT_TRUE(HasTextAt(PC, 0, " Aaa"));
601 }
602 {
603 ParagraphComment *PC;
604 ASSERT_TRUE(GetChildAt(FC, 2, PC));
605
606 ASSERT_TRUE(HasChildCount(PC, 1));
607 ASSERT_TRUE(HasTextAt(PC, 0, " Bbb"));
608 }
609}
610
611TEST_F(CommentParserTest, Paragraph3) {
612 const char *Source = "// \\brief \\author";
613
614 FullComment *FC = parseString(Source);
615 ASSERT_TRUE(HasChildCount(FC, 3));
616
617 {
618 ParagraphComment *PC;
619 ASSERT_TRUE(GetChildAt(FC, 0, PC));
620
621 ASSERT_TRUE(HasChildCount(PC, 1));
622 ASSERT_TRUE(HasTextAt(PC, 0, " "));
623 }
624 {
625 BlockCommandComment *BCC;
626 ParagraphComment *PC;
627 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
628
629 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
630 ASSERT_TRUE(HasChildCount(PC, 1));
631 ASSERT_TRUE(HasTextAt(PC, 0, " "));
632 }
633 {
634 BlockCommandComment *BCC;
635 ParagraphComment *PC;
636 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
637
638 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
639 ASSERT_TRUE(HasChildCount(PC, 0));
640 }
641}
642
643TEST_F(CommentParserTest, Paragraph4) {
644 const char *Source =
645 "// \\brief Aaa\n"
646 "// Bbb \\author\n"
647 "// Ccc";
648
649 FullComment *FC = parseString(Source);
650 ASSERT_TRUE(HasChildCount(FC, 3));
651
652 {
653 ParagraphComment *PC;
654 ASSERT_TRUE(GetChildAt(FC, 0, PC));
655
656 ASSERT_TRUE(HasChildCount(PC, 1));
657 ASSERT_TRUE(HasTextAt(PC, 0, " "));
658 }
659 {
660 BlockCommandComment *BCC;
661 ParagraphComment *PC;
662 ASSERT_TRUE(HasBlockCommandAt(FC, 1, BCC, "brief", PC));
663
664 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
665 ASSERT_TRUE(HasChildCount(PC, 2));
666 ASSERT_TRUE(HasTextWithNewlineAt(PC, 0, " Aaa"));
667 ASSERT_TRUE(HasTextAt(PC, 1, " Bbb "));
668 }
669 {
670 BlockCommandComment *BCC;
671 ParagraphComment *PC;
672 ASSERT_TRUE(HasBlockCommandAt(FC, 2, BCC, "author", PC));
673
674 ASSERT_TRUE(GetChildAt(BCC, 0, PC));
675 ASSERT_TRUE(HasChildCount(PC, 1));
676 ASSERT_TRUE(HasTextAt(PC, 0, " Ccc"));
677 }
678}
679
680TEST_F(CommentParserTest, ParamCommand1) {
681 const char *Source =
682 "// \\param aaa\n"
683 "// \\param [in] aaa\n"
684 "// \\param [out] aaa\n"
685 "// \\param [in,out] aaa\n"
686 "// \\param [in, out] aaa\n";
687
688 FullComment *FC = parseString(Source);
689 ASSERT_TRUE(HasChildCount(FC, 6));
690
691 {
692 ParagraphComment *PC;
693 ASSERT_TRUE(GetChildAt(FC, 0, PC));
694
695 ASSERT_TRUE(HasChildCount(PC, 1));
696 ASSERT_TRUE(HasTextAt(PC, 0, " "));
697 }
698 {
699 ParamCommandComment *PCC;
700 ParagraphComment *PC;
701 ASSERT_TRUE(HasParamCommandAt(FC, 1, PCC, "param",
702 ParamCommandComment::In,
703 /* IsDirectionExplicit = */ false,
704 "aaa", PC));
705 ASSERT_TRUE(HasChildCount(PCC, 1));
706 ASSERT_TRUE(HasChildCount(PC, 1));
707 ASSERT_TRUE(HasTextAt(PC, 0, " "));
708 }
709 {
710 ParamCommandComment *PCC;
711 ParagraphComment *PC;
712 ASSERT_TRUE(HasParamCommandAt(FC, 2, PCC, "param",
713 ParamCommandComment::In,
714 /* IsDirectionExplicit = */ true,
715 "aaa", PC));
716 ASSERT_TRUE(HasChildCount(PCC, 1));
717 ASSERT_TRUE(HasChildCount(PC, 1));
718 ASSERT_TRUE(HasTextAt(PC, 0, " "));
719 }
720 {
721 ParamCommandComment *PCC;
722 ParagraphComment *PC;
723 ASSERT_TRUE(HasParamCommandAt(FC, 3, PCC, "param",
724 ParamCommandComment::Out,
725 /* IsDirectionExplicit = */ true,
726 "aaa", PC));
727 ASSERT_TRUE(HasChildCount(PCC, 1));
728 ASSERT_TRUE(HasChildCount(PC, 1));
729 ASSERT_TRUE(HasTextAt(PC, 0, " "));
730 }
731 {
732 ParamCommandComment *PCC;
733 ParagraphComment *PC;
734 ASSERT_TRUE(HasParamCommandAt(FC, 4, PCC, "param",
735 ParamCommandComment::InOut,
736 /* IsDirectionExplicit = */ true,
737 "aaa", PC));
738 ASSERT_TRUE(HasChildCount(PCC, 1));
739 ASSERT_TRUE(HasChildCount(PC, 1));
740 ASSERT_TRUE(HasTextAt(PC, 0, " "));
741 }
742 {
743 ParamCommandComment *PCC;
744 ParagraphComment *PC;
745 ASSERT_TRUE(HasParamCommandAt(FC, 5, PCC, "param",
746 ParamCommandComment::InOut,
747 /* IsDirectionExplicit = */ true,
748 "aaa", PC));
749 ASSERT_TRUE(HasChildCount(PCC, 1));
750 ASSERT_TRUE(HasChildCount(PC, 0));
751 }
752}
753
754TEST_F(CommentParserTest, InlineCommand1) {
755 const char *Source = "// \\c";
756
757 FullComment *FC = parseString(Source);
758 ASSERT_TRUE(HasChildCount(FC, 1));
759
760 {
761 ParagraphComment *PC;
762 InlineCommandComment *ICC;
763 ASSERT_TRUE(GetChildAt(FC, 0, PC));
764
765 ASSERT_TRUE(HasChildCount(PC, 2));
766 ASSERT_TRUE(HasTextAt(PC, 0, " "));
767 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
768 }
769}
770
771TEST_F(CommentParserTest, InlineCommand2) {
772 const char *Source = "// \\c ";
773
774 FullComment *FC = parseString(Source);
775 ASSERT_TRUE(HasChildCount(FC, 1));
776
777 {
778 ParagraphComment *PC;
779 InlineCommandComment *ICC;
780 ASSERT_TRUE(GetChildAt(FC, 0, PC));
781
782 ASSERT_TRUE(HasChildCount(PC, 3));
783 ASSERT_TRUE(HasTextAt(PC, 0, " "));
784 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", NoArgs()));
785 ASSERT_TRUE(HasTextAt(PC, 2, " "));
786 }
787}
788
789TEST_F(CommentParserTest, InlineCommand3) {
790 const char *Source = "// \\c aaa\n";
791
792 FullComment *FC = parseString(Source);
793 ASSERT_TRUE(HasChildCount(FC, 1));
794
795 {
796 ParagraphComment *PC;
797 InlineCommandComment *ICC;
798 ASSERT_TRUE(GetChildAt(FC, 0, PC));
799
800 ASSERT_TRUE(HasChildCount(PC, 2));
801 ASSERT_TRUE(HasTextAt(PC, 0, " "));
802 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
803 }
804}
805
806TEST_F(CommentParserTest, InlineCommand4) {
807 const char *Source = "// \\c aaa bbb";
808
809 FullComment *FC = parseString(Source);
810 ASSERT_TRUE(HasChildCount(FC, 1));
811
812 {
813 ParagraphComment *PC;
814 InlineCommandComment *ICC;
815 ASSERT_TRUE(GetChildAt(FC, 0, PC));
816
817 ASSERT_TRUE(HasChildCount(PC, 3));
818 ASSERT_TRUE(HasTextAt(PC, 0, " "));
819 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "c", "aaa"));
820 ASSERT_TRUE(HasTextAt(PC, 2, " bbb"));
821 }
822}
823
824TEST_F(CommentParserTest, InlineCommand5) {
825 const char *Source = "// \\unknown aaa\n";
826
827 FullComment *FC = parseString(Source);
828 ASSERT_TRUE(HasChildCount(FC, 1));
829
830 {
831 ParagraphComment *PC;
832 InlineCommandComment *ICC;
833 ASSERT_TRUE(GetChildAt(FC, 0, PC));
834
835 ASSERT_TRUE(HasChildCount(PC, 3));
836 ASSERT_TRUE(HasTextAt(PC, 0, " "));
837 ASSERT_TRUE(HasInlineCommandAt(PC, 1, ICC, "unknown", NoArgs()));
838 ASSERT_TRUE(HasTextAt(PC, 2, " aaa"));
839 }
840}
841
842TEST_F(CommentParserTest, HTML1) {
843 const char *Sources[] = {
844 "// <a",
845 "// <a>",
846 "// <a >"
847 };
848
849 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
850 FullComment *FC = parseString(Sources[i]);
851 ASSERT_TRUE(HasChildCount(FC, 1));
852
853 {
854 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000855 HTMLStartTagComment *HST;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000856 ASSERT_TRUE(GetChildAt(FC, 0, PC));
857
858 ASSERT_TRUE(HasChildCount(PC, 2));
859 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000860 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", NoAttrs()));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000861 }
862 }
863}
864
865TEST_F(CommentParserTest, HTML2) {
866 const char *Sources[] = {
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000867 "// <br/>",
868 "// <br />"
869 };
870
871 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
872 FullComment *FC = parseString(Sources[i]);
873 ASSERT_TRUE(HasChildCount(FC, 1));
874
875 {
876 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000877 HTMLStartTagComment *HST;
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000878 ASSERT_TRUE(GetChildAt(FC, 0, PC));
879
880 ASSERT_TRUE(HasChildCount(PC, 2));
881 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000882 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "br", SelfClosing()));
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000883 }
884 }
885}
886
887TEST_F(CommentParserTest, HTML3) {
888 const char *Sources[] = {
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000889 "// <a href",
890 "// <a href ",
891 "// <a href>",
892 "// <a href >",
893 };
894
895 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
896 FullComment *FC = parseString(Sources[i]);
897 ASSERT_TRUE(HasChildCount(FC, 1));
898
899 {
900 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000901 HTMLStartTagComment *HST;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000902 ASSERT_TRUE(GetChildAt(FC, 0, PC));
903
904 ASSERT_TRUE(HasChildCount(PC, 2));
905 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000906 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", ""));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000907 }
908 }
909}
910
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000911TEST_F(CommentParserTest, HTML4) {
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000912 const char *Sources[] = {
913 "// <a href=\"bbb\"",
914 "// <a href=\"bbb\">",
915 };
916
917 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
918 FullComment *FC = parseString(Sources[i]);
919 ASSERT_TRUE(HasChildCount(FC, 1));
920
921 {
922 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000923 HTMLStartTagComment *HST;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000924 ASSERT_TRUE(GetChildAt(FC, 0, PC));
925
926 ASSERT_TRUE(HasChildCount(PC, 2));
927 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000928 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "a", "href", "bbb"));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000929 }
930 }
931}
932
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000933TEST_F(CommentParserTest, HTML5) {
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000934 const char *Sources[] = {
935 "// </a",
936 "// </a>",
937 "// </a >"
938 };
939
940 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
941 FullComment *FC = parseString(Sources[i]);
942 ASSERT_TRUE(HasChildCount(FC, 1));
943
944 {
945 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000946 HTMLEndTagComment *HET;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000947 ASSERT_TRUE(GetChildAt(FC, 0, PC));
948
949 ASSERT_TRUE(HasChildCount(PC, 2));
950 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000951 ASSERT_TRUE(HasHTMLEndTagAt(PC, 1, HET, "a"));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000952 }
953 }
954}
955
Dmitri Gribenkoa5ef44f2012-07-11 21:38:39 +0000956TEST_F(CommentParserTest, HTML6) {
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000957 const char *Source =
958 "// <pre>\n"
959 "// Aaa\n"
960 "// Bbb\n"
961 "// </pre>\n";
962
963 FullComment *FC = parseString(Source);
964 ASSERT_TRUE(HasChildCount(FC, 1));
965
966 {
967 ParagraphComment *PC;
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000968 HTMLStartTagComment *HST;
969 HTMLEndTagComment *HET;
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000970 ASSERT_TRUE(GetChildAt(FC, 0, PC));
971
972 ASSERT_TRUE(HasChildCount(PC, 6));
973 ASSERT_TRUE(HasTextAt(PC, 0, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000974 ASSERT_TRUE(HasHTMLStartTagAt(PC, 1, HST, "pre", NoAttrs()));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000975 ASSERT_TRUE(HasTextWithNewlineAt(PC, 2, " Aaa"));
976 ASSERT_TRUE(HasTextWithNewlineAt(PC, 3, " Bbb"));
977 ASSERT_TRUE(HasTextAt(PC, 4, " "));
Dmitri Gribenko3f38bf22012-07-13 00:44:24 +0000978 ASSERT_TRUE(HasHTMLEndTagAt(PC, 5, HET, "pre"));
Dmitri Gribenko8d3ba232012-07-06 00:28:32 +0000979 }
980}
981
982TEST_F(CommentParserTest, VerbatimBlock1) {
983 const char *Source = "// \\verbatim\\endverbatim\n";
984
985 FullComment *FC = parseString(Source);
986 ASSERT_TRUE(HasChildCount(FC, 2));
987
988 {
989 ParagraphComment *PC;
990 ASSERT_TRUE(GetChildAt(FC, 0, PC));
991
992 ASSERT_TRUE(HasChildCount(PC, 1));
993 ASSERT_TRUE(HasTextAt(PC, 0, " "));
994 }
995 {
996 VerbatimBlockComment *VCC;
997 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VCC, "verbatim", NoLines()));
998 }
999}
1000
1001TEST_F(CommentParserTest, VerbatimBlock2) {
1002 const char *Source = "// \\verbatim Aaa \\endverbatim\n";
1003
1004 FullComment *FC = parseString(Source);
1005 ASSERT_TRUE(HasChildCount(FC, 2));
1006
1007 {
1008 ParagraphComment *PC;
1009 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1010
1011 ASSERT_TRUE(HasChildCount(PC, 1));
1012 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1013 }
1014 {
1015 VerbatimBlockComment *VBC;
1016 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", " Aaa "));
1017 }
1018}
1019
1020TEST_F(CommentParserTest, VerbatimBlock3) {
1021 const char *Source =
1022 "//\\verbatim\n"
1023 "//\\endverbatim\n";
1024
1025 FullComment *FC = parseString(Source);
1026 ASSERT_TRUE(HasChildCount(FC, 1));
1027
1028 {
1029 VerbatimBlockComment *VBC;
1030 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", NoLines()));
1031 }
1032}
1033
1034TEST_F(CommentParserTest, VerbatimBlock4) {
1035 const char *Sources[] = {
1036 "//\\verbatim\n"
1037 "// Aaa\n"
1038 "//\\endverbatim\n",
1039
1040 "/*\\verbatim\n"
1041 " * Aaa\n"
1042 " *\\endverbatim*/"
1043 };
1044
1045 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1046 FullComment *FC = parseString(Sources[i]);
1047 ASSERT_TRUE(HasChildCount(FC, 1));
1048
1049 {
1050 VerbatimBlockComment *VBC;
1051 ASSERT_TRUE(HasVerbatimBlockAt(FC, 0, VBC, "verbatim", " Aaa"));
1052 }
1053 }
1054}
1055
1056TEST_F(CommentParserTest, VerbatimBlock5) {
1057 const char *Sources[] = {
1058 "// \\verbatim\n"
1059 "// Aaa\n"
1060 "// \\endverbatim\n",
1061
1062 "/* \\verbatim\n"
1063 " * Aaa\n"
1064 " * \\endverbatim*/"
1065 };
1066
1067 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1068 FullComment *FC = parseString(Sources[i]);
1069 ASSERT_TRUE(HasChildCount(FC, 2));
1070
1071 {
1072 ParagraphComment *PC;
1073 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1074
1075 ASSERT_TRUE(HasChildCount(PC, 1));
1076 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1077 }
1078 {
1079 VerbatimBlockComment *VBC;
1080 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim", " Aaa", " "));
1081 }
1082 }
1083}
1084
1085TEST_F(CommentParserTest, VerbatimBlock6) {
1086 const char *Sources[] = {
1087 "// \\verbatim\n"
1088 "// Aaa\n"
1089 "//\n"
1090 "// Bbb\n"
1091 "// \\endverbatim\n",
1092
1093 "/* \\verbatim\n"
1094 " * Aaa\n"
1095 " *\n"
1096 " * Bbb\n"
1097 " * \\endverbatim*/"
1098 };
1099 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1100 FullComment *FC = parseString(Sources[i]);
1101 ASSERT_TRUE(HasChildCount(FC, 2));
1102
1103 {
1104 ParagraphComment *PC;
1105 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1106
1107 ASSERT_TRUE(HasChildCount(PC, 1));
1108 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1109 }
1110 {
1111 VerbatimBlockComment *VBC;
1112 ASSERT_TRUE(HasVerbatimBlockAt(FC, 1, VBC, "verbatim"));
1113 ASSERT_EQ(4U, VBC->getLineCount());
1114 ASSERT_EQ(" Aaa", VBC->getText(0));
1115 ASSERT_EQ("", VBC->getText(1));
1116 ASSERT_EQ(" Bbb", VBC->getText(2));
1117 ASSERT_EQ(" ", VBC->getText(3));
1118 }
1119 }
1120}
1121
1122TEST_F(CommentParserTest, VerbatimLine1) {
1123 const char *Sources[] = {
1124 "// \\fn",
1125 "// \\fn\n"
1126 };
1127
1128 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1129 FullComment *FC = parseString(Sources[i]);
1130 ASSERT_TRUE(HasChildCount(FC, 2));
1131
1132 {
1133 ParagraphComment *PC;
1134 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1135
1136 ASSERT_TRUE(HasChildCount(PC, 1));
1137 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1138 }
1139 {
1140 VerbatimLineComment *VLC;
1141 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn", ""));
1142 }
1143 }
1144}
1145
1146TEST_F(CommentParserTest, VerbatimLine2) {
1147 const char *Sources[] = {
1148 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
1149 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
1150 };
1151
1152 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
1153 FullComment *FC = parseString(Sources[i]);
1154 ASSERT_TRUE(HasChildCount(FC, 2));
1155
1156 {
1157 ParagraphComment *PC;
1158 ASSERT_TRUE(GetChildAt(FC, 0, PC));
1159
1160 ASSERT_TRUE(HasChildCount(PC, 1));
1161 ASSERT_TRUE(HasTextAt(PC, 0, " "));
1162 }
1163 {
1164 VerbatimLineComment *VLC;
1165 ASSERT_TRUE(HasVerbatimLineAt(FC, 1, VLC, "fn",
1166 " void *foo(const char *zzz = \"\\$\");"));
1167 }
1168 }
1169}
1170
1171} // unnamed namespace
1172
1173} // end namespace comments
1174} // end namespace clang
1175