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