CommentHandlerTest.cpp 6.6 KB

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