blob: b73d16ca007559beb2dbe542a50c2d7be9f9378e [file] [log] [blame]
Dmitri Gribenko2d44d772012-06-26 20:39:18 +00001//===- unittests/AST/CommentLexer.cpp ------ Comment lexer 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/CommentLexer.h"
14#include "llvm/ADT/STLExtras.h"
15#include <vector>
16
17#include "gtest/gtest.h"
18
19using namespace llvm;
20using namespace clang;
21
22namespace clang {
23namespace comments {
24
25namespace {
26class CommentLexerTest : public ::testing::Test {
27protected:
28 CommentLexerTest()
29 : FileMgr(FileMgrOpts),
30 DiagID(new DiagnosticIDs()),
31 Diags(DiagID, new IgnoringDiagConsumer()),
32 SourceMgr(Diags, FileMgr) {
33 }
34
35 FileSystemOptions FileMgrOpts;
36 FileManager FileMgr;
37 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
38 DiagnosticsEngine Diags;
39 SourceManager SourceMgr;
40
41 void lexString(const char *Source, std::vector<Token> &Toks);
42};
43
44void CommentLexerTest::lexString(const char *Source,
45 std::vector<Token> &Toks) {
46 MemoryBuffer *Buf = MemoryBuffer::getMemBuffer(Source);
47 FileID File = SourceMgr.createFileIDForMemBuffer(Buf);
48 SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
49
50 comments::Lexer L(Begin, CommentOptions(),
51 Source, Source + strlen(Source));
52
53 while (1) {
54 Token Tok;
55 L.lex(Tok);
56 if (Tok.is(tok::eof))
57 break;
58 Toks.push_back(Tok);
59 }
60}
61
62} // unnamed namespace
63
64// Empty source range should be handled.
65TEST_F(CommentLexerTest, Basic1) {
66 const char *Source = "";
67 std::vector<Token> Toks;
68
69 lexString(Source, Toks);
70
71 ASSERT_EQ(0U, Toks.size());
72}
73
74// Empty comments should be handled.
75TEST_F(CommentLexerTest, Basic2) {
76 const char *Sources[] = {
77 "//", "///", "//!", "///<", "//!<"
78 };
79 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
80 std::vector<Token> Toks;
81
82 lexString(Sources[i], Toks);
83
84 ASSERT_EQ(1U, Toks.size());
85
86 ASSERT_EQ(tok::newline, Toks[0].getKind());
87 }
88}
89
90// Empty comments should be handled.
91TEST_F(CommentLexerTest, Basic3) {
92 const char *Sources[] = {
93 "/**/", "/***/", "/*!*/", "/**<*/", "/*!<*/"
94 };
95 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
96 std::vector<Token> Toks;
97
98 lexString(Sources[i], Toks);
99
100 ASSERT_EQ(2U, Toks.size());
101
102 ASSERT_EQ(tok::newline, Toks[0].getKind());
103 ASSERT_EQ(tok::newline, Toks[1].getKind());
104 }
105}
106
107// Single comment with plain text.
108TEST_F(CommentLexerTest, Basic4) {
109 const char *Sources[] = {
110 "// Meow", "/// Meow", "//! Meow",
111 "// Meow\n", "// Meow\r\n", "//! Meow\r",
112 };
113
114 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
115 std::vector<Token> Toks;
116
117 lexString(Sources[i], Toks);
118
119 ASSERT_EQ(2U, Toks.size());
120
121 ASSERT_EQ(tok::text, Toks[0].getKind());
122 ASSERT_EQ(StringRef(" Meow"), Toks[0].getText());
123
124 ASSERT_EQ(tok::newline, Toks[1].getKind());
125 }
126}
127
128// Single comment with plain text.
129TEST_F(CommentLexerTest, Basic5) {
130 const char *Sources[] = {
131 "/* Meow*/", "/** Meow*/", "/*! Meow*/"
132 };
133
134 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
135 std::vector<Token> Toks;
136
137 lexString(Sources[i], Toks);
138
139 ASSERT_EQ(3U, Toks.size());
140
141 ASSERT_EQ(tok::text, Toks[0].getKind());
142 ASSERT_EQ(StringRef(" Meow"), Toks[0].getText());
143
144 ASSERT_EQ(tok::newline, Toks[1].getKind());
145 ASSERT_EQ(tok::newline, Toks[2].getKind());
146 }
147}
148
149// Test newline escaping.
150TEST_F(CommentLexerTest, Basic6) {
151 const char *Sources[] = {
152 "// Aaa\\\n" " Bbb\\ \n" " Ccc?" "?/\n",
153 "// Aaa\\\r\n" " Bbb\\ \r\n" " Ccc?" "?/\r\n",
154 "// Aaa\\\r" " Bbb\\ \r" " Ccc?" "?/\r"
155 };
156
157 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
158 std::vector<Token> Toks;
159
160 lexString(Sources[i], Toks);
161
162 ASSERT_EQ(10U, Toks.size());
163
164 ASSERT_EQ(tok::text, Toks[0].getKind());
165 ASSERT_EQ(StringRef(" Aaa"), Toks[0].getText());
166 ASSERT_EQ(tok::text, Toks[1].getKind());
167 ASSERT_EQ(StringRef("\\"), Toks[1].getText());
168 ASSERT_EQ(tok::newline, Toks[2].getKind());
169
170 ASSERT_EQ(tok::text, Toks[3].getKind());
171 ASSERT_EQ(StringRef(" Bbb"), Toks[3].getText());
172 ASSERT_EQ(tok::text, Toks[4].getKind());
173 ASSERT_EQ(StringRef("\\"), Toks[4].getText());
174 ASSERT_EQ(tok::text, Toks[5].getKind());
175 ASSERT_EQ(StringRef(" "), Toks[5].getText());
176 ASSERT_EQ(tok::newline, Toks[6].getKind());
177
178 ASSERT_EQ(tok::text, Toks[7].getKind());
179 ASSERT_EQ(StringRef(" Ccc?" "?/"), Toks[7].getText());
180 ASSERT_EQ(tok::newline, Toks[8].getKind());
181
182 ASSERT_EQ(tok::newline, Toks[9].getKind());
183 }
184}
185
186// Check that we skip C-style aligned stars correctly.
187TEST_F(CommentLexerTest, Basic7) {
188 const char *Source =
189 "/* Aaa\n"
190 " * Bbb\r\n"
191 "\t* Ccc\n"
192 " ! Ddd\n"
193 " * Eee\n"
194 " ** Fff\n"
195 " */";
196 std::vector<Token> Toks;
197
198 lexString(Source, Toks);
199
200 ASSERT_EQ(15U, Toks.size());
201
202 ASSERT_EQ(tok::text, Toks[0].getKind());
203 ASSERT_EQ(StringRef(" Aaa"), Toks[0].getText());
204 ASSERT_EQ(tok::newline, Toks[1].getKind());
205
206 ASSERT_EQ(tok::text, Toks[2].getKind());
207 ASSERT_EQ(StringRef(" Bbb"), Toks[2].getText());
208 ASSERT_EQ(tok::newline, Toks[3].getKind());
209
210 ASSERT_EQ(tok::text, Toks[4].getKind());
211 ASSERT_EQ(StringRef(" Ccc"), Toks[4].getText());
212 ASSERT_EQ(tok::newline, Toks[5].getKind());
213
214 ASSERT_EQ(tok::text, Toks[6].getKind());
215 ASSERT_EQ(StringRef(" ! Ddd"), Toks[6].getText());
216 ASSERT_EQ(tok::newline, Toks[7].getKind());
217
218 ASSERT_EQ(tok::text, Toks[8].getKind());
219 ASSERT_EQ(StringRef(" Eee"), Toks[8].getText());
220 ASSERT_EQ(tok::newline, Toks[9].getKind());
221
222 ASSERT_EQ(tok::text, Toks[10].getKind());
223 ASSERT_EQ(StringRef("* Fff"), Toks[10].getText());
224 ASSERT_EQ(tok::newline, Toks[11].getKind());
225
226 ASSERT_EQ(tok::text, Toks[12].getKind());
227 ASSERT_EQ(StringRef(" "), Toks[12].getText());
228
229 ASSERT_EQ(tok::newline, Toks[13].getKind());
230 ASSERT_EQ(tok::newline, Toks[14].getKind());
231}
232
233// A command marker followed by comment end.
234TEST_F(CommentLexerTest, DoxygenCommand1) {
235 const char *Sources[] = { "//@", "///@", "//!@" };
236 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
237 std::vector<Token> Toks;
238
239 lexString(Sources[i], Toks);
240
241 ASSERT_EQ(2U, Toks.size());
242
243 ASSERT_EQ(tok::text, Toks[0].getKind());
244 ASSERT_EQ(StringRef("@"), Toks[0].getText());
245
246 ASSERT_EQ(tok::newline, Toks[1].getKind());
247 }
248}
249
250// A command marker followed by comment end.
251TEST_F(CommentLexerTest, DoxygenCommand2) {
252 const char *Sources[] = { "/*@*/", "/**@*/", "/*!@*/"};
253 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
254 std::vector<Token> Toks;
255
256 lexString(Sources[i], Toks);
257
258 ASSERT_EQ(3U, Toks.size());
259
260 ASSERT_EQ(tok::text, Toks[0].getKind());
261 ASSERT_EQ(StringRef("@"), Toks[0].getText());
262
263 ASSERT_EQ(tok::newline, Toks[1].getKind());
264 ASSERT_EQ(tok::newline, Toks[2].getKind());
265 }
266}
267
268// A command marker followed by comment end.
269TEST_F(CommentLexerTest, DoxygenCommand3) {
270 const char *Sources[] = { "/*\\*/", "/**\\*/" };
271 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
272 std::vector<Token> Toks;
273
274 lexString(Sources[i], Toks);
275
276 ASSERT_EQ(3U, Toks.size());
277
278 ASSERT_EQ(tok::text, Toks[0].getKind());
279 ASSERT_EQ(StringRef("\\"), Toks[0].getText());
280
281 ASSERT_EQ(tok::newline, Toks[1].getKind());
282 ASSERT_EQ(tok::newline, Toks[2].getKind());
283 }
284}
285
286// Doxygen escape sequences.
287TEST_F(CommentLexerTest, DoxygenCommand4) {
288 const char *Source =
289 "/// \\\\ \\@ \\& \\$ \\# \\< \\> \\% \\\" \\. \\::";
290 const char *Text[] = {
291 " ",
292 "\\", " ", "@", " ", "&", " ", "$", " ", "#", " ",
293 "<", " ", ">", " ", "%", " ", "\"", " ", ".", " ",
294 "::", ""
295 };
296
297 std::vector<Token> Toks;
298
299 lexString(Source, Toks);
300
301 ASSERT_EQ(array_lengthof(Text), Toks.size());
302
303 for (size_t i = 0, e = Toks.size(); i != e; i++) {
304 if(Toks[i].is(tok::text))
305 ASSERT_EQ(StringRef(Text[i]), Toks[i].getText())
306 << "index " << i;
307 }
308}
309
310TEST_F(CommentLexerTest, DoxygenCommand5) {
311 const char *Source = "/// \\brief Aaa.";
312 std::vector<Token> Toks;
313
314 lexString(Source, Toks);
315
316 ASSERT_EQ(4U, Toks.size());
317
318 ASSERT_EQ(tok::text, Toks[0].getKind());
319 ASSERT_EQ(StringRef(" "), Toks[0].getText());
320
321 ASSERT_EQ(tok::command, Toks[1].getKind());
322 ASSERT_EQ(StringRef("brief"), Toks[1].getCommandName());
323
324 ASSERT_EQ(tok::text, Toks[2].getKind());
325 ASSERT_EQ(StringRef(" Aaa."), Toks[2].getText());
326
327 ASSERT_EQ(tok::newline, Toks[3].getKind());
328}
329
330TEST_F(CommentLexerTest, DoxygenCommand6) {
331 const char *Source = "/// \\aaa\\bbb \\ccc\t\\ddd\n";
332 std::vector<Token> Toks;
333
334 lexString(Source, Toks);
335
336 ASSERT_EQ(8U, Toks.size());
337
338 ASSERT_EQ(tok::text, Toks[0].getKind());
339 ASSERT_EQ(StringRef(" "), Toks[0].getText());
340
341 ASSERT_EQ(tok::command, Toks[1].getKind());
342 ASSERT_EQ(StringRef("aaa"), Toks[1].getCommandName());
343
344 ASSERT_EQ(tok::command, Toks[2].getKind());
345 ASSERT_EQ(StringRef("bbb"), Toks[2].getCommandName());
346
347 ASSERT_EQ(tok::text, Toks[3].getKind());
348 ASSERT_EQ(StringRef(" "), Toks[3].getText());
349
350 ASSERT_EQ(tok::command, Toks[4].getKind());
351 ASSERT_EQ(StringRef("ccc"), Toks[4].getCommandName());
352
353 ASSERT_EQ(tok::text, Toks[5].getKind());
354 ASSERT_EQ(StringRef("\t"), Toks[5].getText());
355
356 ASSERT_EQ(tok::command, Toks[6].getKind());
357 ASSERT_EQ(StringRef("ddd"), Toks[6].getCommandName());
358
359 ASSERT_EQ(tok::newline, Toks[7].getKind());
360}
361
362// Empty verbatim block.
363TEST_F(CommentLexerTest, VerbatimBlock1) {
364 const char *Sources[] = {
365 "/// \\verbatim\\endverbatim\n//",
366 "/** \\verbatim\\endverbatim*/"
367 };
368
369 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
370 std::vector<Token> Toks;
371
372 lexString(Sources[i], Toks);
373
374 ASSERT_EQ(5U, Toks.size());
375
376 ASSERT_EQ(tok::text, Toks[0].getKind());
377 ASSERT_EQ(StringRef(" "), Toks[0].getText());
378
379 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
380 ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
381
382 ASSERT_EQ(tok::verbatim_block_end, Toks[2].getKind());
383 ASSERT_EQ(StringRef("endverbatim"), Toks[2].getVerbatimBlockName());
384
385 ASSERT_EQ(tok::newline, Toks[3].getKind());
386 ASSERT_EQ(tok::newline, Toks[4].getKind());
387 }
388}
389
390// Empty verbatim block without an end command.
391TEST_F(CommentLexerTest, VerbatimBlock2) {
392 const char *Sources[] = {
393 "/// \\verbatim\n//",
394 "/** \\verbatim*/"
395 };
396
397 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
398 std::vector<Token> Toks;
399
400 lexString(Sources[i], Toks);
401
402 ASSERT_EQ(4U, Toks.size());
403
404 ASSERT_EQ(tok::text, Toks[0].getKind());
405 ASSERT_EQ(StringRef(" "), Toks[0].getText());
406
407 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
408 ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
409
410 ASSERT_EQ(tok::newline, Toks[2].getKind());
411 ASSERT_EQ(tok::newline, Toks[3].getKind());
412 }
413}
414
415// Single-line verbatim block.
416TEST_F(CommentLexerTest, VerbatimBlock3) {
417 const char *Sources[] = {
418 "/// Meow \\verbatim aaa \\endverbatim\n//",
419 "/** Meow \\verbatim aaa \\endverbatim*/"
420 };
421
422 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
423 std::vector<Token> Toks;
424
425 lexString(Sources[i], Toks);
426
427 ASSERT_EQ(6U, Toks.size());
428
429 ASSERT_EQ(tok::text, Toks[0].getKind());
430 ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
431
432 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
433 ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
434
435 ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
436 ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText());
437
438 ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind());
439 ASSERT_EQ(StringRef("endverbatim"), Toks[3].getVerbatimBlockName());
440
441 ASSERT_EQ(tok::newline, Toks[4].getKind());
442 ASSERT_EQ(tok::newline, Toks[5].getKind());
443 }
444}
445
446// Single-line verbatim block without an end command.
447TEST_F(CommentLexerTest, VerbatimBlock4) {
448 const char *Sources[] = {
449 "/// Meow \\verbatim aaa \n//",
450 "/** Meow \\verbatim aaa */"
451 };
452
453 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
454 std::vector<Token> Toks;
455
456 lexString(Sources[i], Toks);
457
458 ASSERT_EQ(5U, Toks.size());
459
460 ASSERT_EQ(tok::text, Toks[0].getKind());
461 ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
462
463 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
464 ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
465
466 ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
467 ASSERT_EQ(StringRef(" aaa "), Toks[2].getVerbatimBlockText());
468
469 ASSERT_EQ(tok::newline, Toks[3].getKind());
470 ASSERT_EQ(tok::newline, Toks[4].getKind());
471 }
472}
473
474// Complex test for verbatim blocks.
475TEST_F(CommentLexerTest, VerbatimBlock5) {
476 const char *Source =
477 "/* Meow \\verbatim aaa\\$\\@\n"
478 "bbb \\endverbati\r"
479 "ccc\r\n"
480 "ddd \\endverbatim Blah \\verbatim eee\n"
481 "\\endverbatim BlahBlah*/";
482 std::vector<Token> Toks;
483
484 lexString(Source, Toks);
485
486 ASSERT_EQ(14U, Toks.size());
487
488 ASSERT_EQ(tok::text, Toks[0].getKind());
489 ASSERT_EQ(StringRef(" Meow "), Toks[0].getText());
490
491 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
492 ASSERT_EQ(StringRef("verbatim"), Toks[1].getVerbatimBlockName());
493
494 ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
495 ASSERT_EQ(StringRef(" aaa\\$\\@\n"), Toks[2].getVerbatimBlockText());
496
497 ASSERT_EQ(tok::verbatim_block_line, Toks[3].getKind());
498 ASSERT_EQ(StringRef("bbb \\endverbati\r"), Toks[3].getVerbatimBlockText());
499
500 ASSERT_EQ(tok::verbatim_block_line, Toks[4].getKind());
501 ASSERT_EQ(StringRef("ccc\r\n"), Toks[4].getVerbatimBlockText());
502
503 ASSERT_EQ(tok::verbatim_block_line, Toks[5].getKind());
504 ASSERT_EQ(StringRef("ddd "), Toks[5].getVerbatimBlockText());
505
506 ASSERT_EQ(tok::verbatim_block_end, Toks[6].getKind());
507 ASSERT_EQ(StringRef("endverbatim"), Toks[6].getVerbatimBlockName());
508
509 ASSERT_EQ(tok::text, Toks[7].getKind());
510 ASSERT_EQ(StringRef(" Blah "), Toks[7].getText());
511
512 ASSERT_EQ(tok::verbatim_block_begin, Toks[8].getKind());
513 ASSERT_EQ(StringRef("verbatim"), Toks[8].getVerbatimBlockName());
514
515 ASSERT_EQ(tok::verbatim_block_line, Toks[9].getKind());
516 ASSERT_EQ(StringRef(" eee\n"), Toks[9].getVerbatimBlockText());
517
518 ASSERT_EQ(tok::verbatim_block_end, Toks[10].getKind());
519 ASSERT_EQ(StringRef("endverbatim"), Toks[10].getVerbatimBlockName());
520
521 ASSERT_EQ(tok::text, Toks[11].getKind());
522 ASSERT_EQ(StringRef(" BlahBlah"), Toks[11].getText());
523
524 ASSERT_EQ(tok::newline, Toks[12].getKind());
525 ASSERT_EQ(tok::newline, Toks[13].getKind());
526}
527
528// LaTeX verbatim blocks.
529TEST_F(CommentLexerTest, VerbatimBlock6) {
530 const char *Source =
531 "/// \\f$ Aaa \\f$ \\f[ Bbb \\f] \\f{ Ccc \\f}";
532 std::vector<Token> Toks;
533
534 lexString(Source, Toks);
535
536 ASSERT_EQ(13U, Toks.size());
537
538 ASSERT_EQ(tok::text, Toks[0].getKind());
539 ASSERT_EQ(StringRef(" "), Toks[0].getText());
540
541 ASSERT_EQ(tok::verbatim_block_begin, Toks[1].getKind());
542 ASSERT_EQ(StringRef("f$"), Toks[1].getVerbatimBlockName());
543
544 ASSERT_EQ(tok::verbatim_block_line, Toks[2].getKind());
545 ASSERT_EQ(StringRef(" Aaa "), Toks[2].getVerbatimBlockText());
546
547 ASSERT_EQ(tok::verbatim_block_end, Toks[3].getKind());
548 ASSERT_EQ(StringRef("f$"), Toks[3].getVerbatimBlockName());
549
550 ASSERT_EQ(tok::text, Toks[4].getKind());
551 ASSERT_EQ(StringRef(" "), Toks[4].getText());
552
553 ASSERT_EQ(tok::verbatim_block_begin, Toks[5].getKind());
554 ASSERT_EQ(StringRef("f["), Toks[5].getVerbatimBlockName());
555
556 ASSERT_EQ(tok::verbatim_block_line, Toks[6].getKind());
557 ASSERT_EQ(StringRef(" Bbb "), Toks[6].getVerbatimBlockText());
558
559 ASSERT_EQ(tok::verbatim_block_end, Toks[7].getKind());
560 ASSERT_EQ(StringRef("f]"), Toks[7].getVerbatimBlockName());
561
562 ASSERT_EQ(tok::text, Toks[8].getKind());
563 ASSERT_EQ(StringRef(" "), Toks[8].getText());
564
565 ASSERT_EQ(tok::verbatim_block_begin, Toks[9].getKind());
566 ASSERT_EQ(StringRef("f{"), Toks[9].getVerbatimBlockName());
567
568 ASSERT_EQ(tok::verbatim_block_line, Toks[10].getKind());
569 ASSERT_EQ(StringRef(" Ccc "), Toks[10].getVerbatimBlockText());
570
571 ASSERT_EQ(tok::verbatim_block_end, Toks[11].getKind());
572 ASSERT_EQ(StringRef("f}"), Toks[11].getVerbatimBlockName());
573
574 ASSERT_EQ(tok::newline, Toks[12].getKind());
575}
576
577// Empty verbatim line.
578TEST_F(CommentLexerTest, VerbatimLine1) {
579 const char *Sources[] = {
580 "/// \\fn\n//",
581 "/** \\fn*/"
582 };
583
584 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
585 std::vector<Token> Toks;
586
587 lexString(Sources[i], Toks);
588
589 ASSERT_EQ(4U, Toks.size());
590
591 ASSERT_EQ(tok::text, Toks[0].getKind());
592 ASSERT_EQ(StringRef(" "), Toks[0].getText());
593
594 ASSERT_EQ(tok::verbatim_line, Toks[1].getKind());
595 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
596 ASSERT_EQ(StringRef(""), Toks[1].getVerbatimLineText());
597
598 ASSERT_EQ(tok::newline, Toks[2].getKind());
599 ASSERT_EQ(tok::newline, Toks[3].getKind());
600 }
601}
602
603// Verbatim line with Doxygen escape sequences, which should not be expanded.
604TEST_F(CommentLexerTest, VerbatimLine2) {
605 const char *Sources[] = {
606 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
607 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
608 };
609
610 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
611 std::vector<Token> Toks;
612
613 lexString(Sources[i], Toks);
614
615 ASSERT_EQ(4U, Toks.size());
616
617 ASSERT_EQ(tok::text, Toks[0].getKind());
618 ASSERT_EQ(StringRef(" "), Toks[0].getText());
619
620 ASSERT_EQ(tok::verbatim_line, Toks[1].getKind());
621 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
622 ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
623 Toks[1].getVerbatimLineText());
624
625 ASSERT_EQ(tok::newline, Toks[2].getKind());
626 ASSERT_EQ(tok::newline, Toks[3].getKind());
627 }
628}
629
630// Verbatim line should not eat anything from next source line.
631TEST_F(CommentLexerTest, VerbatimLine3) {
632 const char *Source =
633 "/** \\fn void *foo(const char *zzz = \"\\$\");\n"
634 " * Meow\n"
635 " */";
636
637 std::vector<Token> Toks;
638
639 lexString(Source, Toks);
640
641 ASSERT_EQ(8U, Toks.size());
642
643 ASSERT_EQ(tok::text, Toks[0].getKind());
644 ASSERT_EQ(StringRef(" "), Toks[0].getText());
645
646 ASSERT_EQ(tok::verbatim_line, Toks[1].getKind());
647 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
648 ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
649 Toks[1].getVerbatimLineText());
650 ASSERT_EQ(tok::newline, Toks[2].getKind());
651
652 ASSERT_EQ(tok::text, Toks[3].getKind());
653 ASSERT_EQ(StringRef(" Meow"), Toks[3].getText());
654 ASSERT_EQ(tok::newline, Toks[4].getKind());
655
656 ASSERT_EQ(tok::text, Toks[5].getKind());
657 ASSERT_EQ(StringRef(" "), Toks[5].getText());
658
659 ASSERT_EQ(tok::newline, Toks[6].getKind());
660 ASSERT_EQ(tok::newline, Toks[7].getKind());
661}
662
663TEST_F(CommentLexerTest, HTML1) {
664 const char *Source =
665 "// <";
666
667 std::vector<Token> Toks;
668
669 lexString(Source, Toks);
670
671 ASSERT_EQ(3U, Toks.size());
672
673 ASSERT_EQ(tok::text, Toks[0].getKind());
674 ASSERT_EQ(StringRef(" "), Toks[0].getText());
675
676 ASSERT_EQ(tok::text, Toks[1].getKind());
677 ASSERT_EQ(StringRef("<"), Toks[1].getText());
678
679 ASSERT_EQ(tok::newline, Toks[2].getKind());
680}
681
682TEST_F(CommentLexerTest, HTML2) {
683 const char *Sources[] = {
684 "// <tag",
685 "// <tag "
686 };
687
688 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
689 std::vector<Token> Toks;
690
691 lexString(Sources[i], Toks);
692
693 ASSERT_EQ(3U, Toks.size());
694
695 ASSERT_EQ(tok::text, Toks[0].getKind());
696 ASSERT_EQ(StringRef(" "), Toks[0].getText());
697
698 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
699 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
700
701 ASSERT_EQ(tok::newline, Toks[2].getKind());
702 }
703}
704
705TEST_F(CommentLexerTest, HTML3) {
706 const char *Source = "// <tag=";
707
708 std::vector<Token> Toks;
709
710 lexString(Source, Toks);
711
712 ASSERT_EQ(4U, Toks.size());
713
714 ASSERT_EQ(tok::text, Toks[0].getKind());
715 ASSERT_EQ(StringRef(" "), Toks[0].getText());
716
717 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
718 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
719
720 ASSERT_EQ(tok::text, Toks[2].getKind());
721 ASSERT_EQ(StringRef("="), Toks[2].getText());
722
723 ASSERT_EQ(tok::newline, Toks[3].getKind());
724}
725
726TEST_F(CommentLexerTest, HTML4) {
727 const char *Sources[] = {
728 "// <tag attr",
729 "// <tag attr "
730 };
731
732 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
733 std::vector<Token> Toks;
734
735 lexString(Sources[i], Toks);
736
737 ASSERT_EQ(4U, Toks.size());
738
739 ASSERT_EQ(tok::text, Toks[0].getKind());
740 ASSERT_EQ(StringRef(" "), Toks[0].getText());
741
742 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
743 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
744
745 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
746 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
747
748 ASSERT_EQ(tok::newline, Toks[3].getKind());
749 }
750}
751
752TEST_F(CommentLexerTest, HTML5) {
753 const char *Sources[] = {
754 "// <tag attr=",
755 "// <tag attr ="
756 };
757
758 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
759 std::vector<Token> Toks;
760
761 lexString(Sources[i], Toks);
762
763 ASSERT_EQ(5U, Toks.size());
764
765 ASSERT_EQ(tok::text, Toks[0].getKind());
766 ASSERT_EQ(StringRef(" "), Toks[0].getText());
767
768 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
769 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
770
771 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
772 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
773
774 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
775
776 ASSERT_EQ(tok::newline, Toks[4].getKind());
777 }
778}
779
780TEST_F(CommentLexerTest, HTML6) {
781 const char *Sources[] = {
782 "// <tag attr=\"",
783 "// <tag attr = \"",
784 "// <tag attr=\'",
785 "// <tag attr = \'"
786 };
787
788 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
789 std::vector<Token> Toks;
790
791 lexString(Sources[i], Toks);
792
793 ASSERT_EQ(6U, Toks.size());
794
795 ASSERT_EQ(tok::text, Toks[0].getKind());
796 ASSERT_EQ(StringRef(" "), Toks[0].getText());
797
798 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
799 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
800
801 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
802 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
803
804 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
805
806 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
807 ASSERT_EQ(StringRef(""), Toks[4].getHTMLQuotedString());
808
809 ASSERT_EQ(tok::newline, Toks[5].getKind());
810 }
811}
812
813TEST_F(CommentLexerTest, HTML7) {
814 const char *Source = "// <tag attr=@";
815
816 std::vector<Token> Toks;
817
818 lexString(Source, Toks);
819
820 ASSERT_EQ(6U, Toks.size());
821
822 ASSERT_EQ(tok::text, Toks[0].getKind());
823 ASSERT_EQ(StringRef(" "), Toks[0].getText());
824
825 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
826 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
827
828 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
829 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
830
831 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
832
833 ASSERT_EQ(tok::text, Toks[4].getKind());
834 ASSERT_EQ(StringRef("@"), Toks[4].getText());
835
836 ASSERT_EQ(tok::newline, Toks[5].getKind());
837}
838
839TEST_F(CommentLexerTest, HTML8) {
840 const char *Sources[] = {
841 "// <tag attr=\"val\\\"\\'val",
842 "// <tag attr=\"val\\\"\\'val\"",
843 "// <tag attr=\'val\\\"\\'val",
844 "// <tag attr=\'val\\\"\\'val\'"
845 };
846
847 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
848 std::vector<Token> Toks;
849
850 lexString(Sources[i], Toks);
851
852 ASSERT_EQ(6U, Toks.size());
853
854 ASSERT_EQ(tok::text, Toks[0].getKind());
855 ASSERT_EQ(StringRef(" "), Toks[0].getText());
856
857 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
858 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
859
860 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
861 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
862
863 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
864
865 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
866 ASSERT_EQ(StringRef("val\\\"\\'val"), Toks[4].getHTMLQuotedString());
867
868 ASSERT_EQ(tok::newline, Toks[5].getKind());
869 }
870}
871
872TEST_F(CommentLexerTest, HTML9) {
873 const char *Sources[] = {
874 "// <tag attr=\"val\\\"\\'val\">",
875 "// <tag attr=\'val\\\"\\'val\'>"
876 };
877
878 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
879 std::vector<Token> Toks;
880
881 lexString(Sources[i], Toks);
882
883 ASSERT_EQ(7U, Toks.size());
884
885 ASSERT_EQ(tok::text, Toks[0].getKind());
886 ASSERT_EQ(StringRef(" "), Toks[0].getText());
887
888 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
889 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
890
891 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
892 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
893
894 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
895
896 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
897 ASSERT_EQ(StringRef("val\\\"\\'val"), Toks[4].getHTMLQuotedString());
898
899 ASSERT_EQ(tok::html_greater, Toks[5].getKind());
900
901 ASSERT_EQ(tok::newline, Toks[6].getKind());
902 }
903}
904
905TEST_F(CommentLexerTest, HTML10) {
906 const char *Source = "// </";
907
908 std::vector<Token> Toks;
909
910 lexString(Source, Toks);
911
912 ASSERT_EQ(3U, Toks.size());
913
914 ASSERT_EQ(tok::text, Toks[0].getKind());
915 ASSERT_EQ(StringRef(" "), Toks[0].getText());
916
917 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
918 ASSERT_EQ(StringRef(""), Toks[1].getHTMLTagCloseName());
919
920 ASSERT_EQ(tok::newline, Toks[2].getKind());
921}
922
923
924TEST_F(CommentLexerTest, HTML11) {
925 const char *Source = "// </@";
926
927 std::vector<Token> Toks;
928
929 lexString(Source, Toks);
930
931 ASSERT_EQ(4U, Toks.size());
932
933 ASSERT_EQ(tok::text, Toks[0].getKind());
934 ASSERT_EQ(StringRef(" "), Toks[0].getText());
935
936 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
937 ASSERT_EQ(StringRef(""), Toks[1].getHTMLTagCloseName());
938
939 ASSERT_EQ(tok::text, Toks[2].getKind());
940 ASSERT_EQ(StringRef("@"), Toks[2].getText());
941
942 ASSERT_EQ(tok::newline, Toks[3].getKind());
943}
944
945TEST_F(CommentLexerTest, HTML12) {
946 const char *Sources[] = {
947 "// </tag",
948 "// </tag>",
949 "// </ tag>",
950 "// </ tag >"
951 };
952
953 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
954 std::vector<Token> Toks;
955
956 lexString(Sources[i], Toks);
957
958 ASSERT_EQ(3U, Toks.size());
959
960 ASSERT_EQ(tok::text, Toks[0].getKind());
961 ASSERT_EQ(StringRef(" "), Toks[0].getText());
962
963 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
964 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagCloseName());
965
966 ASSERT_EQ(tok::newline, Toks[2].getKind());
967 }
968}
969
970TEST_F(CommentLexerTest, MultipleComments) {
971 const char *Source =
972 "// Aaa\n"
973 "/// Bbb\n"
974 "/* Ccc\n"
975 " * Ddd*/\n"
976 "/** Eee*/";
977
978 std::vector<Token> Toks;
979
980 lexString(Source, Toks);
981
982 ASSERT_EQ(12U, Toks.size());
983
984 ASSERT_EQ(tok::text, Toks[0].getKind());
985 ASSERT_EQ(StringRef(" Aaa"), Toks[0].getText());
986 ASSERT_EQ(tok::newline, Toks[1].getKind());
987
988 ASSERT_EQ(tok::text, Toks[2].getKind());
989 ASSERT_EQ(StringRef(" Bbb"), Toks[2].getText());
990 ASSERT_EQ(tok::newline, Toks[3].getKind());
991
992 ASSERT_EQ(tok::text, Toks[4].getKind());
993 ASSERT_EQ(StringRef(" Ccc"), Toks[4].getText());
994 ASSERT_EQ(tok::newline, Toks[5].getKind());
995
996 ASSERT_EQ(tok::text, Toks[6].getKind());
997 ASSERT_EQ(StringRef(" Ddd"), Toks[6].getText());
998 ASSERT_EQ(tok::newline, Toks[7].getKind());
999 ASSERT_EQ(tok::newline, Toks[8].getKind());
1000
1001 ASSERT_EQ(tok::text, Toks[9].getKind());
1002 ASSERT_EQ(StringRef(" Eee"), Toks[9].getText());
1003
1004 ASSERT_EQ(tok::newline, Toks[10].getKind());
1005 ASSERT_EQ(tok::newline, Toks[11].getKind());
1006}
1007
1008} // end namespace comments
1009} // end namespace clang
1010