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