CommentHandlerTest.cpp 6.5 KB

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