//===--- ClangTidyTest.h - clang-tidy ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H #include "ClangTidy.h" #include "ClangTidyDiagnosticConsumer.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Tooling.h" #include namespace clang { namespace tidy { namespace test { class TestClangTidyAction : public ASTFrontendAction { public: TestClangTidyAction(ClangTidyCheck &Check, ast_matchers::MatchFinder &Finder, ClangTidyContext &Context) : Check(Check), Finder(Finder), Context(Context) {} private: std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, StringRef File) override { Context.setSourceManager(&Compiler.getSourceManager()); Context.setCurrentFile(File); Context.setASTContext(&Compiler.getASTContext()); Check.registerMatchers(&Finder); Check.registerPPCallbacks(Compiler); return Finder.newASTConsumer(); } ClangTidyCheck &Check; ast_matchers::MatchFinder &Finder; ClangTidyContext &Context; }; template std::string runCheckOnCode(StringRef Code, std::vector *Errors = nullptr, const Twine &Filename = "input.cc", ArrayRef ExtraArgs = None, const ClangTidyOptions &ExtraOptions = ClangTidyOptions(), std::map PathsToContent = std::map()) { ClangTidyOptions Options = ExtraOptions; Options.Checks = "*"; ClangTidyContext Context(llvm::make_unique( ClangTidyGlobalOptions(), Options)); ClangTidyDiagnosticConsumer DiagConsumer(Context); T Check("test-check", &Context); std::vector ArgCXX11(1, "clang-tidy"); ArgCXX11.push_back("-fsyntax-only"); ArgCXX11.push_back("-std=c++11"); ArgCXX11.push_back("-Iinclude"); ArgCXX11.insert(ArgCXX11.end(), ExtraArgs.begin(), ExtraArgs.end()); ArgCXX11.push_back(Filename.str()); ast_matchers::MatchFinder Finder; llvm::IntrusiveRefCntPtr Files( new FileManager(FileSystemOptions())); tooling::ToolInvocation Invocation( ArgCXX11, new TestClangTidyAction(Check, Finder, Context), Files.get()); Invocation.mapVirtualFile(Filename.str(), Code); for (const auto &FileContent : PathsToContent) { Invocation.mapVirtualFile(Twine("include/" + FileContent.first).str(), FileContent.second); } Invocation.setDiagnosticConsumer(&DiagConsumer); if (!Invocation.run()) { std::string ErrorText; for (const auto &Error : Context.getErrors()) { ErrorText += Error.Message.Message + "\n"; } llvm::report_fatal_error(ErrorText); } DiagConsumer.finish(); tooling::Replacements Fixes; for (const ClangTidyError &Error : Context.getErrors()) Fixes.insert(Error.Fix.begin(), Error.Fix.end()); if (Errors) *Errors = Context.getErrors(); return tooling::applyAllReplacements(Code, Fixes); } #define EXPECT_NO_CHANGES(Check, Code) \ EXPECT_EQ(Code, runCheckOnCode(Code)) } // namespace test } // namespace tidy } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H