blob: b42b28b9c9486f44be54bd4430c49b6a1054cba8 [file] [log] [blame]
Richard Smith87d8fb92012-06-24 23:56:26 +00001//===- unittest/Tooling/CommentHandlerTest.cpp -----------------------===//
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 "TestVisitor.h"
11#include "clang/Lex/Preprocessor.h"
12
13namespace clang {
14
15struct Comment {
16 Comment(const std::string &Message, unsigned Line, unsigned Col)
17 : Message(Message), Line(Line), Col(Col) { }
18
19 std::string Message;
20 unsigned Line, Col;
21};
22
23class CommentVerifier;
24typedef std::vector<Comment> CommentList;
25
26class CommentHandlerVisitor : public TestVisitor<CommentHandlerVisitor>,
27 public CommentHandler {
28 typedef TestVisitor<CommentHandlerVisitor> base;
29
30public:
Craig Topper416fa342014-06-08 08:38:12 +000031 CommentHandlerVisitor() : base(), PP(nullptr), Verified(false) {}
Richard Smith87d8fb92012-06-24 23:56:26 +000032
Alexander Kornienko34eb2072015-04-11 02:00:23 +000033 ~CommentHandlerVisitor() override {
Richard Smith87d8fb92012-06-24 23:56:26 +000034 EXPECT_TRUE(Verified) << "CommentVerifier not accessed";
35 }
36
Alexander Kornienko34eb2072015-04-11 02:00:23 +000037 bool HandleComment(Preprocessor &PP, SourceRange Loc) override {
Richard Smith87d8fb92012-06-24 23:56:26 +000038 assert(&PP == this->PP && "Preprocessor changed!");
39
40 SourceLocation Start = Loc.getBegin();
41 SourceManager &SM = PP.getSourceManager();
42 std::string C(SM.getCharacterData(Start),
43 SM.getCharacterData(Loc.getEnd()));
44
45 bool Invalid;
46 unsigned CLine = SM.getSpellingLineNumber(Start, &Invalid);
47 EXPECT_TRUE(!Invalid) << "Invalid line number on comment " << C;
48
49 unsigned CCol = SM.getSpellingColumnNumber(Start, &Invalid);
50 EXPECT_TRUE(!Invalid) << "Invalid column number on comment " << C;
51
52 Comments.push_back(Comment(C, CLine, CCol));
53 return false;
54 }
55
56 CommentVerifier GetVerifier();
57
58protected:
Alexander Kornienko34eb2072015-04-11 02:00:23 +000059 ASTFrontendAction *CreateTestAction() override {
Richard Smith87d8fb92012-06-24 23:56:26 +000060 return new CommentHandlerAction(this);
61 }
62
63private:
64 Preprocessor *PP;
65 CommentList Comments;
66 bool Verified;
67
68 class CommentHandlerAction : public base::TestAction {
69 public:
70 CommentHandlerAction(CommentHandlerVisitor *Visitor)
71 : TestAction(Visitor) { }
72
Alexander Kornienko34eb2072015-04-11 02:00:23 +000073 bool BeginSourceFileAction(CompilerInstance &CI,
74 StringRef FileName) override {
Richard Smith87d8fb92012-06-24 23:56:26 +000075 CommentHandlerVisitor *V =
76 static_cast<CommentHandlerVisitor*>(this->Visitor);
77 V->PP = &CI.getPreprocessor();
78 V->PP->addCommentHandler(V);
79 return true;
80 }
81
Alexander Kornienko34eb2072015-04-11 02:00:23 +000082 void EndSourceFileAction() override {
Richard Smith87d8fb92012-06-24 23:56:26 +000083 CommentHandlerVisitor *V =
84 static_cast<CommentHandlerVisitor*>(this->Visitor);
85 V->PP->removeCommentHandler(V);
86 }
87 };
88};
89
90class CommentVerifier {
91 CommentList::const_iterator Current;
92 CommentList::const_iterator End;
93 Preprocessor *PP;
94
95public:
96 CommentVerifier(const CommentList &Comments, Preprocessor *PP)
97 : Current(Comments.begin()), End(Comments.end()), PP(PP)
98 { }
99
David Blaikiee4381272015-08-13 21:24:08 +0000100 CommentVerifier(CommentVerifier &&C) : Current(C.Current), End(C.End), PP(C.PP) {
101 C.Current = C.End;
102 }
103
Richard Smith87d8fb92012-06-24 23:56:26 +0000104 ~CommentVerifier() {
105 if (Current != End) {
106 EXPECT_TRUE(Current == End) << "Unexpected comment \""
107 << Current->Message << "\" at line " << Current->Line << ", column "
108 << Current->Col;
109 }
110 }
111
112 void Match(const char *Message, unsigned Line, unsigned Col) {
113 EXPECT_TRUE(Current != End) << "Comment " << Message << " not found";
114 if (Current == End) return;
115
116 const Comment &C = *Current;
117 EXPECT_TRUE(C.Message == Message && C.Line == Line && C.Col == Col)
118 << "Expected comment \"" << Message
119 << "\" at line " << Line << ", column " << Col
120 << "\nActual comment \"" << C.Message
121 << "\" at line " << C.Line << ", column " << C.Col;
122
123 ++Current;
124 }
125};
126
127CommentVerifier CommentHandlerVisitor::GetVerifier() {
128 Verified = true;
129 return CommentVerifier(Comments, PP);
130}
131
132
133TEST(CommentHandlerTest, BasicTest1) {
134 CommentHandlerVisitor Visitor;
135 EXPECT_TRUE(Visitor.runOver("class X {}; int main() { return 0; }"));
136 CommentVerifier Verifier = Visitor.GetVerifier();
137}
138
139TEST(CommentHandlerTest, BasicTest2) {
140 CommentHandlerVisitor Visitor;
141 EXPECT_TRUE(Visitor.runOver(
142 "class X {}; int main() { /* comment */ return 0; }"));
143 CommentVerifier Verifier = Visitor.GetVerifier();
144 Verifier.Match("/* comment */", 1, 26);
145}
146
147TEST(CommentHandlerTest, BasicTest3) {
148 CommentHandlerVisitor Visitor;
149 EXPECT_TRUE(Visitor.runOver(
150 "class X {}; // comment 1\n"
151 "int main() {\n"
152 " // comment 2\n"
153 " return 0;\n"
154 "}"));
155 CommentVerifier Verifier = Visitor.GetVerifier();
156 Verifier.Match("// comment 1", 1, 13);
157 Verifier.Match("// comment 2", 3, 3);
158}
159
160TEST(CommentHandlerTest, IfBlock1) {
161 CommentHandlerVisitor Visitor;
162 EXPECT_TRUE(Visitor.runOver(
163 "#if 0\n"
164 "// ignored comment\n"
165 "#endif\n"
166 "// visible comment\n"));
167 CommentVerifier Verifier = Visitor.GetVerifier();
168 Verifier.Match("// visible comment", 4, 1);
169}
170
171TEST(CommentHandlerTest, IfBlock2) {
172 CommentHandlerVisitor Visitor;
173 EXPECT_TRUE(Visitor.runOver(
174 "#define TEST // visible_1\n"
175 "#ifndef TEST // visible_2\n"
176 " // ignored_3\n"
177 "# ifdef UNDEFINED // ignored_4\n"
178 "# endif // ignored_5\n"
179 "#elif defined(TEST) // visible_6\n"
180 "# if 1 // visible_7\n"
181 " // visible_8\n"
182 "# else // visible_9\n"
183 " // ignored_10\n"
184 "# ifndef TEST // ignored_11\n"
185 "# endif // ignored_12\n"
186 "# endif // visible_13\n"
187 "#endif // visible_14\n"));
188
189 CommentVerifier Verifier = Visitor.GetVerifier();
190 Verifier.Match("// visible_1", 1, 21);
191 Verifier.Match("// visible_2", 2, 21);
192 Verifier.Match("// visible_6", 6, 21);
193 Verifier.Match("// visible_7", 7, 21);
194 Verifier.Match("// visible_8", 8, 21);
195 Verifier.Match("// visible_9", 9, 21);
196 Verifier.Match("// visible_13", 13, 21);
197 Verifier.Match("// visible_14", 14, 21);
198}
199
200TEST(CommentHandlerTest, IfBlock3) {
201 const char *Source =
202 "/* commented out ...\n"
203 "#if 0\n"
204 "// enclosed\n"
205 "#endif */";
206
207 CommentHandlerVisitor Visitor;
208 EXPECT_TRUE(Visitor.runOver(Source));
209 CommentVerifier Verifier = Visitor.GetVerifier();
210 Verifier.Match(Source, 1, 1);
211}
212
213TEST(CommentHandlerTest, PPDirectives) {
214 CommentHandlerVisitor Visitor;
215 EXPECT_TRUE(Visitor.runOver(
216 "#warning Y // ignored_1\n" // #warning takes whole line as message
217 "#undef MACRO // visible_2\n"
218 "#line 1 // visible_3\n"));
219
220 CommentVerifier Verifier = Visitor.GetVerifier();
221 Verifier.Match("// visible_2", 2, 14);
222 Verifier.Match("// visible_3", 3, 14);
223}
224
225} // end namespace clang