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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/unittests/Tooling/CommentHandlerTest.cpp