blob: 5b4712df2599760a9d8f4ad16a60c7b4a3a2115d [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
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000591 ASSERT_EQ(tok::text, Toks[0].getKind());
592 ASSERT_EQ(StringRef(" "), Toks[0].getText());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000593
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000594 ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
595 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000596
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000597 ASSERT_EQ(tok::newline, Toks[2].getKind());
598 ASSERT_EQ(tok::newline, Toks[3].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000599 }
600}
601
602// Verbatim line with Doxygen escape sequences, which should not be expanded.
603TEST_F(CommentLexerTest, VerbatimLine2) {
604 const char *Sources[] = {
605 "/// \\fn void *foo(const char *zzz = \"\\$\");\n//",
606 "/** \\fn void *foo(const char *zzz = \"\\$\");*/"
607 };
608
609 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
610 std::vector<Token> Toks;
611
612 lexString(Sources[i], Toks);
613
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000614 ASSERT_EQ(5U, Toks.size());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000615
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000616 ASSERT_EQ(tok::text, Toks[0].getKind());
617 ASSERT_EQ(StringRef(" "), Toks[0].getText());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000618
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000619 ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
620 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
621
622 ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000623 ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000624 Toks[2].getVerbatimLineText());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000625
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000626 ASSERT_EQ(tok::newline, Toks[3].getKind());
627 ASSERT_EQ(tok::newline, Toks[4].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000628 }
629}
630
631// Verbatim line should not eat anything from next source line.
632TEST_F(CommentLexerTest, VerbatimLine3) {
633 const char *Source =
634 "/** \\fn void *foo(const char *zzz = \"\\$\");\n"
635 " * Meow\n"
636 " */";
637
638 std::vector<Token> Toks;
639
640 lexString(Source, Toks);
641
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000642 ASSERT_EQ(9U, Toks.size());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000643
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000644 ASSERT_EQ(tok::text, Toks[0].getKind());
645 ASSERT_EQ(StringRef(" "), Toks[0].getText());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000646
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000647 ASSERT_EQ(tok::verbatim_line_name, Toks[1].getKind());
648 ASSERT_EQ(StringRef("fn"), Toks[1].getVerbatimLineName());
649
650 ASSERT_EQ(tok::verbatim_line_text, Toks[2].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000651 ASSERT_EQ(StringRef(" void *foo(const char *zzz = \"\\$\");"),
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000652 Toks[2].getVerbatimLineText());
653 ASSERT_EQ(tok::newline, Toks[3].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000654
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000655 ASSERT_EQ(tok::text, Toks[4].getKind());
656 ASSERT_EQ(StringRef(" Meow"), Toks[4].getText());
657 ASSERT_EQ(tok::newline, Toks[5].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000658
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000659 ASSERT_EQ(tok::text, Toks[6].getKind());
660 ASSERT_EQ(StringRef(" "), Toks[6].getText());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000661
Dmitri Gribenko962668d2012-06-27 16:53:58 +0000662 ASSERT_EQ(tok::newline, Toks[7].getKind());
663 ASSERT_EQ(tok::newline, Toks[8].getKind());
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000664}
665
666TEST_F(CommentLexerTest, HTML1) {
667 const char *Source =
668 "// <";
669
670 std::vector<Token> Toks;
671
672 lexString(Source, Toks);
673
674 ASSERT_EQ(3U, Toks.size());
675
676 ASSERT_EQ(tok::text, Toks[0].getKind());
677 ASSERT_EQ(StringRef(" "), Toks[0].getText());
678
679 ASSERT_EQ(tok::text, Toks[1].getKind());
680 ASSERT_EQ(StringRef("<"), Toks[1].getText());
681
682 ASSERT_EQ(tok::newline, Toks[2].getKind());
683}
684
685TEST_F(CommentLexerTest, HTML2) {
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000686 const char *Source =
687 "// < tag";
688
689 std::vector<Token> Toks;
690
691 lexString(Source, Toks);
692
693 ASSERT_EQ(4U, Toks.size());
694
695 ASSERT_EQ(tok::text, Toks[0].getKind());
696 ASSERT_EQ(StringRef(" "), Toks[0].getText());
697
698 ASSERT_EQ(tok::text, Toks[1].getKind());
699 ASSERT_EQ(StringRef("<"), Toks[1].getText());
700
701 ASSERT_EQ(tok::text, Toks[2].getKind());
702 ASSERT_EQ(StringRef(" tag"), Toks[2].getText());
703
704 ASSERT_EQ(tok::newline, Toks[3].getKind());
705}
706
707TEST_F(CommentLexerTest, HTML3) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000708 const char *Sources[] = {
709 "// <tag",
710 "// <tag "
711 };
712
713 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
714 std::vector<Token> Toks;
715
716 lexString(Sources[i], Toks);
717
718 ASSERT_EQ(3U, Toks.size());
719
720 ASSERT_EQ(tok::text, Toks[0].getKind());
721 ASSERT_EQ(StringRef(" "), Toks[0].getText());
722
723 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
724 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
725
726 ASSERT_EQ(tok::newline, Toks[2].getKind());
727 }
728}
729
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000730TEST_F(CommentLexerTest, HTML4) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000731 const char *Source = "// <tag=";
732
733 std::vector<Token> Toks;
734
735 lexString(Source, 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::text, Toks[2].getKind());
746 ASSERT_EQ(StringRef("="), Toks[2].getText());
747
748 ASSERT_EQ(tok::newline, Toks[3].getKind());
749}
750
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000751TEST_F(CommentLexerTest, HTML5) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000752 const char *Sources[] = {
753 "// <tag attr",
754 "// <tag attr "
755 };
756
757 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
758 std::vector<Token> Toks;
759
760 lexString(Sources[i], Toks);
761
762 ASSERT_EQ(4U, Toks.size());
763
764 ASSERT_EQ(tok::text, Toks[0].getKind());
765 ASSERT_EQ(StringRef(" "), Toks[0].getText());
766
767 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
768 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
769
770 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
771 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
772
773 ASSERT_EQ(tok::newline, Toks[3].getKind());
774 }
775}
776
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000777TEST_F(CommentLexerTest, HTML6) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000778 const char *Sources[] = {
779 "// <tag attr=",
780 "// <tag attr ="
781 };
782
783 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
784 std::vector<Token> Toks;
785
786 lexString(Sources[i], Toks);
787
788 ASSERT_EQ(5U, Toks.size());
789
790 ASSERT_EQ(tok::text, Toks[0].getKind());
791 ASSERT_EQ(StringRef(" "), Toks[0].getText());
792
793 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
794 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
795
796 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
797 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
798
799 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
800
801 ASSERT_EQ(tok::newline, Toks[4].getKind());
802 }
803}
804
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000805TEST_F(CommentLexerTest, HTML7) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000806 const char *Sources[] = {
807 "// <tag attr=\"",
808 "// <tag attr = \"",
809 "// <tag attr=\'",
810 "// <tag attr = \'"
811 };
812
813 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
814 std::vector<Token> Toks;
815
816 lexString(Sources[i], Toks);
817
818 ASSERT_EQ(6U, Toks.size());
819
820 ASSERT_EQ(tok::text, Toks[0].getKind());
821 ASSERT_EQ(StringRef(" "), Toks[0].getText());
822
823 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
824 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
825
826 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
827 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
828
829 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
830
831 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
832 ASSERT_EQ(StringRef(""), Toks[4].getHTMLQuotedString());
833
834 ASSERT_EQ(tok::newline, Toks[5].getKind());
835 }
836}
837
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000838TEST_F(CommentLexerTest, HTML8) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000839 const char *Source = "// <tag attr=@";
840
841 std::vector<Token> Toks;
842
843 lexString(Source, Toks);
844
845 ASSERT_EQ(6U, Toks.size());
846
847 ASSERT_EQ(tok::text, Toks[0].getKind());
848 ASSERT_EQ(StringRef(" "), Toks[0].getText());
849
850 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
851 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
852
853 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
854 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
855
856 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
857
858 ASSERT_EQ(tok::text, Toks[4].getKind());
859 ASSERT_EQ(StringRef("@"), Toks[4].getText());
860
861 ASSERT_EQ(tok::newline, Toks[5].getKind());
862}
863
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000864TEST_F(CommentLexerTest, HTML9) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000865 const char *Sources[] = {
866 "// <tag attr=\"val\\\"\\'val",
867 "// <tag attr=\"val\\\"\\'val\"",
868 "// <tag attr=\'val\\\"\\'val",
869 "// <tag attr=\'val\\\"\\'val\'"
870 };
871
872 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
873 std::vector<Token> Toks;
874
875 lexString(Sources[i], Toks);
876
877 ASSERT_EQ(6U, Toks.size());
878
879 ASSERT_EQ(tok::text, Toks[0].getKind());
880 ASSERT_EQ(StringRef(" "), Toks[0].getText());
881
882 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
883 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
884
885 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
886 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
887
888 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
889
890 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
891 ASSERT_EQ(StringRef("val\\\"\\'val"), Toks[4].getHTMLQuotedString());
892
893 ASSERT_EQ(tok::newline, Toks[5].getKind());
894 }
895}
896
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000897TEST_F(CommentLexerTest, HTML10) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000898 const char *Sources[] = {
899 "// <tag attr=\"val\\\"\\'val\">",
900 "// <tag attr=\'val\\\"\\'val\'>"
901 };
902
903 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
904 std::vector<Token> Toks;
905
906 lexString(Sources[i], Toks);
907
908 ASSERT_EQ(7U, Toks.size());
909
910 ASSERT_EQ(tok::text, Toks[0].getKind());
911 ASSERT_EQ(StringRef(" "), Toks[0].getText());
912
913 ASSERT_EQ(tok::html_tag_open, Toks[1].getKind());
914 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagOpenName());
915
916 ASSERT_EQ(tok::html_ident, Toks[2].getKind());
917 ASSERT_EQ(StringRef("attr"), Toks[2].getHTMLIdent());
918
919 ASSERT_EQ(tok::html_equals, Toks[3].getKind());
920
921 ASSERT_EQ(tok::html_quoted_string, Toks[4].getKind());
922 ASSERT_EQ(StringRef("val\\\"\\'val"), Toks[4].getHTMLQuotedString());
923
924 ASSERT_EQ(tok::html_greater, Toks[5].getKind());
925
926 ASSERT_EQ(tok::newline, Toks[6].getKind());
927 }
928}
929
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000930TEST_F(CommentLexerTest, HTML11) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000931 const char *Source = "// </";
932
933 std::vector<Token> Toks;
934
935 lexString(Source, Toks);
936
937 ASSERT_EQ(3U, Toks.size());
938
939 ASSERT_EQ(tok::text, Toks[0].getKind());
940 ASSERT_EQ(StringRef(" "), Toks[0].getText());
941
942 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
943 ASSERT_EQ(StringRef(""), Toks[1].getHTMLTagCloseName());
944
945 ASSERT_EQ(tok::newline, Toks[2].getKind());
946}
947
948
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000949TEST_F(CommentLexerTest, HTML12) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000950 const char *Source = "// </@";
951
952 std::vector<Token> Toks;
953
954 lexString(Source, Toks);
955
956 ASSERT_EQ(4U, Toks.size());
957
958 ASSERT_EQ(tok::text, Toks[0].getKind());
959 ASSERT_EQ(StringRef(" "), Toks[0].getText());
960
961 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
962 ASSERT_EQ(StringRef(""), Toks[1].getHTMLTagCloseName());
963
964 ASSERT_EQ(tok::text, Toks[2].getKind());
965 ASSERT_EQ(StringRef("@"), Toks[2].getText());
966
967 ASSERT_EQ(tok::newline, Toks[3].getKind());
968}
969
Dmitri Gribenko5676d322012-06-27 23:28:29 +0000970TEST_F(CommentLexerTest, HTML13) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000971 const char *Sources[] = {
972 "// </tag",
973 "// </tag>",
974 "// </ tag>",
975 "// </ tag >"
976 };
977
978 for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
979 std::vector<Token> Toks;
980
981 lexString(Sources[i], Toks);
982
983 ASSERT_EQ(3U, Toks.size());
984
985 ASSERT_EQ(tok::text, Toks[0].getKind());
986 ASSERT_EQ(StringRef(" "), Toks[0].getText());
987
988 ASSERT_EQ(tok::html_tag_close, Toks[1].getKind());
989 ASSERT_EQ(StringRef("tag"), Toks[1].getHTMLTagCloseName());
990
991 ASSERT_EQ(tok::newline, Toks[2].getKind());
992 }
993}
994
995TEST_F(CommentLexerTest, MultipleComments) {
996 const char *Source =
997 "// Aaa\n"
998 "/// Bbb\n"
999 "/* Ccc\n"
1000 " * Ddd*/\n"
1001 "/** Eee*/";
1002
1003 std::vector<Token> Toks;
1004
1005 lexString(Source, Toks);
1006
1007 ASSERT_EQ(12U, Toks.size());
1008
1009 ASSERT_EQ(tok::text, Toks[0].getKind());
1010 ASSERT_EQ(StringRef(" Aaa"), Toks[0].getText());
1011 ASSERT_EQ(tok::newline, Toks[1].getKind());
1012
1013 ASSERT_EQ(tok::text, Toks[2].getKind());
1014 ASSERT_EQ(StringRef(" Bbb"), Toks[2].getText());
1015 ASSERT_EQ(tok::newline, Toks[3].getKind());
1016
1017 ASSERT_EQ(tok::text, Toks[4].getKind());
1018 ASSERT_EQ(StringRef(" Ccc"), Toks[4].getText());
1019 ASSERT_EQ(tok::newline, Toks[5].getKind());
1020
1021 ASSERT_EQ(tok::text, Toks[6].getKind());
1022 ASSERT_EQ(StringRef(" Ddd"), Toks[6].getText());
1023 ASSERT_EQ(tok::newline, Toks[7].getKind());
1024 ASSERT_EQ(tok::newline, Toks[8].getKind());
1025
1026 ASSERT_EQ(tok::text, Toks[9].getKind());
1027 ASSERT_EQ(StringRef(" Eee"), Toks[9].getText());
1028
1029 ASSERT_EQ(tok::newline, Toks[10].getKind());
1030 ASSERT_EQ(tok::newline, Toks[11].getKind());
1031}
1032
1033} // end namespace comments
1034} // end namespace clang
1035