1 //===- unittest/Tooling/CommentHandlerTest.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "TestVisitor.h"
11 #include "clang/Lex/Preprocessor.h"
16 Comment(const std::string &Message, unsigned Line, unsigned Col)
17 : Message(Message), Line(Line), Col(Col) { }
23 class CommentVerifier;
24 typedef std::vector<Comment> CommentList;
26 class CommentHandlerVisitor : public TestVisitor<CommentHandlerVisitor>,
27 public CommentHandler {
28 typedef TestVisitor<CommentHandlerVisitor> base;
31 CommentHandlerVisitor() : base(), PP(nullptr), Verified(false) {}
33 ~CommentHandlerVisitor() override {
34 EXPECT_TRUE(Verified) << "CommentVerifier not accessed";
37 bool HandleComment(Preprocessor &PP, SourceRange Loc) override {
38 assert(&PP == this->PP && "Preprocessor changed!");
40 SourceLocation Start = Loc.getBegin();
41 SourceManager &SM = PP.getSourceManager();
42 std::string C(SM.getCharacterData(Start),
43 SM.getCharacterData(Loc.getEnd()));
46 unsigned CLine = SM.getSpellingLineNumber(Start, &Invalid);
47 EXPECT_TRUE(!Invalid) << "Invalid line number on comment " << C;
49 unsigned CCol = SM.getSpellingColumnNumber(Start, &Invalid);
50 EXPECT_TRUE(!Invalid) << "Invalid column number on comment " << C;
52 Comments.push_back(Comment(C, CLine, CCol));
56 CommentVerifier GetVerifier();
59 ASTFrontendAction *CreateTestAction() override {
60 return new CommentHandlerAction(this);
68 class CommentHandlerAction : public base::TestAction {
70 CommentHandlerAction(CommentHandlerVisitor *Visitor)
71 : TestAction(Visitor) { }
73 bool BeginSourceFileAction(CompilerInstance &CI,
74 StringRef FileName) override {
75 CommentHandlerVisitor *V =
76 static_cast<CommentHandlerVisitor*>(this->Visitor);
77 V->PP = &CI.getPreprocessor();
78 V->PP->addCommentHandler(V);
82 void EndSourceFileAction() override {
83 CommentHandlerVisitor *V =
84 static_cast<CommentHandlerVisitor*>(this->Visitor);
85 V->PP->removeCommentHandler(V);
90 class CommentVerifier {
91 CommentList::const_iterator Current;
92 CommentList::const_iterator End;
96 CommentVerifier(const CommentList &Comments, Preprocessor *PP)
97 : Current(Comments.begin()), End(Comments.end()), PP(PP)
101 if (Current != End) {
102 EXPECT_TRUE(Current == End) << "Unexpected comment \""
103 << Current->Message << "\" at line " << Current->Line << ", column "
108 void Match(const char *Message, unsigned Line, unsigned Col) {
109 EXPECT_TRUE(Current != End) << "Comment " << Message << " not found";
110 if (Current == End) return;
112 const Comment &C = *Current;
113 EXPECT_TRUE(C.Message == Message && C.Line == Line && C.Col == Col)
114 << "Expected comment \"" << Message
115 << "\" at line " << Line << ", column " << Col
116 << "\nActual comment \"" << C.Message
117 << "\" at line " << C.Line << ", column " << C.Col;
123 CommentVerifier CommentHandlerVisitor::GetVerifier() {
125 return CommentVerifier(Comments, PP);
129 TEST(CommentHandlerTest, BasicTest1) {
130 CommentHandlerVisitor Visitor;
131 EXPECT_TRUE(Visitor.runOver("class X {}; int main() { return 0; }"));
132 CommentVerifier Verifier = Visitor.GetVerifier();
135 TEST(CommentHandlerTest, BasicTest2) {
136 CommentHandlerVisitor Visitor;
137 EXPECT_TRUE(Visitor.runOver(
138 "class X {}; int main() { /* comment */ return 0; }"));
139 CommentVerifier Verifier = Visitor.GetVerifier();
140 Verifier.Match("/* comment */", 1, 26);
143 TEST(CommentHandlerTest, BasicTest3) {
144 CommentHandlerVisitor Visitor;
145 EXPECT_TRUE(Visitor.runOver(
146 "class X {}; // comment 1\n"
151 CommentVerifier Verifier = Visitor.GetVerifier();
152 Verifier.Match("// comment 1", 1, 13);
153 Verifier.Match("// comment 2", 3, 3);
156 TEST(CommentHandlerTest, IfBlock1) {
157 CommentHandlerVisitor Visitor;
158 EXPECT_TRUE(Visitor.runOver(
160 "// ignored comment\n"
162 "// visible comment\n"));
163 CommentVerifier Verifier = Visitor.GetVerifier();
164 Verifier.Match("// visible comment", 4, 1);
167 TEST(CommentHandlerTest, IfBlock2) {
168 CommentHandlerVisitor Visitor;
169 EXPECT_TRUE(Visitor.runOver(
170 "#define TEST // visible_1\n"
171 "#ifndef TEST // visible_2\n"
173 "# ifdef UNDEFINED // ignored_4\n"
174 "# endif // ignored_5\n"
175 "#elif defined(TEST) // visible_6\n"
176 "# if 1 // visible_7\n"
178 "# else // visible_9\n"
180 "# ifndef TEST // ignored_11\n"
181 "# endif // ignored_12\n"
182 "# endif // visible_13\n"
183 "#endif // visible_14\n"));
185 CommentVerifier Verifier = Visitor.GetVerifier();
186 Verifier.Match("// visible_1", 1, 21);
187 Verifier.Match("// visible_2", 2, 21);
188 Verifier.Match("// visible_6", 6, 21);
189 Verifier.Match("// visible_7", 7, 21);
190 Verifier.Match("// visible_8", 8, 21);
191 Verifier.Match("// visible_9", 9, 21);
192 Verifier.Match("// visible_13", 13, 21);
193 Verifier.Match("// visible_14", 14, 21);
196 TEST(CommentHandlerTest, IfBlock3) {
198 "/* commented out ...\n"
203 CommentHandlerVisitor Visitor;
204 EXPECT_TRUE(Visitor.runOver(Source));
205 CommentVerifier Verifier = Visitor.GetVerifier();
206 Verifier.Match(Source, 1, 1);
209 TEST(CommentHandlerTest, PPDirectives) {
210 CommentHandlerVisitor Visitor;
211 EXPECT_TRUE(Visitor.runOver(
212 "#warning Y // ignored_1\n" // #warning takes whole line as message
213 "#undef MACRO // visible_2\n"
214 "#line 1 // visible_3\n"));
216 CommentVerifier Verifier = Visitor.GetVerifier();
217 Verifier.Match("// visible_2", 2, 14);
218 Verifier.Match("// visible_3", 3, 14);
221 } // end namespace clang