forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			222 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- unittest/Tooling/CommentHandlerTest.cpp -----------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "TestVisitor.h"
 | |
| #include "clang/Lex/Preprocessor.h"
 | |
| 
 | |
| namespace clang {
 | |
| 
 | |
| struct Comment {
 | |
|   Comment(const std::string &Message, unsigned Line, unsigned Col)
 | |
|     : Message(Message), Line(Line), Col(Col) { }
 | |
| 
 | |
|   std::string Message;
 | |
|   unsigned Line, Col;
 | |
| };
 | |
| 
 | |
| class CommentVerifier;
 | |
| typedef std::vector<Comment> CommentList;
 | |
| 
 | |
| class CommentHandlerVisitor : public TestVisitor<CommentHandlerVisitor>,
 | |
|                               public CommentHandler {
 | |
|   typedef TestVisitor<CommentHandlerVisitor> base;
 | |
| 
 | |
| public:
 | |
|   CommentHandlerVisitor() : base(), PP(0), Verified(false) { }
 | |
| 
 | |
|   ~CommentHandlerVisitor() {
 | |
|     EXPECT_TRUE(Verified) << "CommentVerifier not accessed";
 | |
|   }
 | |
| 
 | |
|   virtual bool HandleComment(Preprocessor &PP, SourceRange Loc) {
 | |
|     assert(&PP == this->PP && "Preprocessor changed!");
 | |
| 
 | |
|     SourceLocation Start = Loc.getBegin();
 | |
|     SourceManager &SM = PP.getSourceManager();
 | |
|     std::string C(SM.getCharacterData(Start),
 | |
|                   SM.getCharacterData(Loc.getEnd()));
 | |
| 
 | |
|     bool Invalid;
 | |
|     unsigned CLine = SM.getSpellingLineNumber(Start, &Invalid);
 | |
|     EXPECT_TRUE(!Invalid) << "Invalid line number on comment " << C;
 | |
| 
 | |
|     unsigned CCol = SM.getSpellingColumnNumber(Start, &Invalid);
 | |
|     EXPECT_TRUE(!Invalid) << "Invalid column number on comment " << C;
 | |
| 
 | |
|     Comments.push_back(Comment(C, CLine, CCol));
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   CommentVerifier GetVerifier();
 | |
| 
 | |
| protected:
 | |
|   virtual ASTFrontendAction* CreateTestAction() {
 | |
|     return new CommentHandlerAction(this);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   Preprocessor *PP;
 | |
|   CommentList Comments;
 | |
|   bool Verified;
 | |
| 
 | |
|   class CommentHandlerAction : public base::TestAction {
 | |
|   public:
 | |
|     CommentHandlerAction(CommentHandlerVisitor *Visitor)
 | |
|         : TestAction(Visitor) { }
 | |
| 
 | |
|     virtual bool BeginSourceFileAction(CompilerInstance &CI,
 | |
|                                        StringRef FileName) {
 | |
|       CommentHandlerVisitor *V =
 | |
|           static_cast<CommentHandlerVisitor*>(this->Visitor);
 | |
|       V->PP = &CI.getPreprocessor();
 | |
|       V->PP->addCommentHandler(V);
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     virtual void EndSourceFileAction() {
 | |
|       CommentHandlerVisitor *V =
 | |
|           static_cast<CommentHandlerVisitor*>(this->Visitor);
 | |
|       V->PP->removeCommentHandler(V);
 | |
|     }
 | |
|   };
 | |
| };
 | |
| 
 | |
| class CommentVerifier {
 | |
|   CommentList::const_iterator Current;
 | |
|   CommentList::const_iterator End;
 | |
|   Preprocessor *PP;
 | |
| 
 | |
| public:
 | |
|   CommentVerifier(const CommentList &Comments, Preprocessor *PP)
 | |
|       : Current(Comments.begin()), End(Comments.end()), PP(PP)
 | |
|     { }
 | |
| 
 | |
|   ~CommentVerifier() {
 | |
|     if (Current != End) {
 | |
|       EXPECT_TRUE(Current == End) << "Unexpected comment \""
 | |
|         << Current->Message << "\" at line " << Current->Line << ", column "
 | |
|         << Current->Col;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void Match(const char *Message, unsigned Line, unsigned Col) {
 | |
|     EXPECT_TRUE(Current != End) << "Comment " << Message << " not found";
 | |
|     if (Current == End) return;
 | |
| 
 | |
|     const Comment &C = *Current;
 | |
|     EXPECT_TRUE(C.Message == Message && C.Line == Line && C.Col == Col)
 | |
|       <<   "Expected comment \"" << Message
 | |
|       << "\" at line " << Line   << ", column " << Col
 | |
|       << "\nActual comment   \"" << C.Message
 | |
|       << "\" at line " << C.Line << ", column " << C.Col;
 | |
| 
 | |
|     ++Current;
 | |
|   }
 | |
| };
 | |
| 
 | |
| CommentVerifier CommentHandlerVisitor::GetVerifier() {
 | |
|   Verified = true;
 | |
|   return CommentVerifier(Comments, PP);
 | |
| }
 | |
| 
 | |
| 
 | |
| TEST(CommentHandlerTest, BasicTest1) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver("class X {}; int main() { return 0; }"));
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, BasicTest2) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(
 | |
|         "class X {}; int main() { /* comment */ return 0; }"));
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match("/* comment */", 1, 26);
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, BasicTest3) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(
 | |
|         "class X {}; // comment 1\n"
 | |
|         "int main() {\n"
 | |
|         "  // comment 2\n"
 | |
|         "  return 0;\n"
 | |
|         "}"));
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match("// comment 1", 1, 13);
 | |
|   Verifier.Match("// comment 2", 3, 3);
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, IfBlock1) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(
 | |
|         "#if 0\n"
 | |
|         "// ignored comment\n"
 | |
|         "#endif\n"
 | |
|         "// visible comment\n"));
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match("// visible comment", 4, 1);
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, IfBlock2) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(
 | |
|         "#define TEST        // visible_1\n"
 | |
|         "#ifndef TEST        // visible_2\n"
 | |
|         "                    // ignored_3\n"
 | |
|         "# ifdef UNDEFINED   // ignored_4\n"
 | |
|         "# endif             // ignored_5\n"
 | |
|         "#elif defined(TEST) // visible_6\n"
 | |
|         "# if 1              // visible_7\n"
 | |
|         "                    // visible_8\n"
 | |
|         "# else              // visible_9\n"
 | |
|         "                    // ignored_10\n"
 | |
|         "#  ifndef TEST      // ignored_11\n"
 | |
|         "#  endif            // ignored_12\n"
 | |
|         "# endif             // visible_13\n"
 | |
|         "#endif              // visible_14\n"));
 | |
| 
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match("// visible_1", 1, 21);
 | |
|   Verifier.Match("// visible_2", 2, 21);
 | |
|   Verifier.Match("// visible_6", 6, 21);
 | |
|   Verifier.Match("// visible_7", 7, 21);
 | |
|   Verifier.Match("// visible_8", 8, 21);
 | |
|   Verifier.Match("// visible_9", 9, 21);
 | |
|   Verifier.Match("// visible_13", 13, 21);
 | |
|   Verifier.Match("// visible_14", 14, 21);
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, IfBlock3) {
 | |
|   const char *Source =
 | |
|         "/* commented out ...\n"
 | |
|         "#if 0\n"
 | |
|         "// enclosed\n"
 | |
|         "#endif */";
 | |
| 
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(Source));
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match(Source, 1, 1);
 | |
| }
 | |
| 
 | |
| TEST(CommentHandlerTest, PPDirectives) {
 | |
|   CommentHandlerVisitor Visitor;
 | |
|   EXPECT_TRUE(Visitor.runOver(
 | |
|         "#warning Y   // ignored_1\n" // #warning takes whole line as message
 | |
|         "#undef MACRO // visible_2\n"
 | |
|         "#line 1      // visible_3\n"));
 | |
| 
 | |
|   CommentVerifier Verifier = Visitor.GetVerifier();
 | |
|   Verifier.Match("// visible_2", 2, 14);
 | |
|   Verifier.Match("// visible_3", 3, 14);
 | |
| }
 | |
| 
 | |
| } // end namespace clang
 |