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