blob: a199274e6e5a69da14adcc4a1ffa42cf1c6a27ba [file] [log] [blame]
Daniel Jasperd07c8402013-07-29 08:19:24 +00001//===--- ClangTidyTest.h - clang-tidy ---------------------------*- C++ -*-===//
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
Alexander Kornienko66580552015-03-09 16:52:33 +000010#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H
11#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H
Daniel Jasperd07c8402013-07-29 08:19:24 +000012
13#include "ClangTidy.h"
14#include "ClangTidyDiagnosticConsumer.h"
15#include "clang/ASTMatchers/ASTMatchFinder.h"
16#include "clang/Frontend/CompilerInstance.h"
17#include "clang/Frontend/FrontendActions.h"
18#include "clang/Tooling/Refactoring.h"
19#include "clang/Tooling/Tooling.h"
Manuel Klimekd00d6f12015-08-11 11:37:48 +000020#include <map>
Daniel Jasperd07c8402013-07-29 08:19:24 +000021
22namespace clang {
23namespace tidy {
Alexander Kornienko09887162014-02-27 14:28:02 +000024namespace test {
Daniel Jasperd07c8402013-07-29 08:19:24 +000025
Manuel Klimek05510652014-10-07 15:49:36 +000026class TestClangTidyAction : public ASTFrontendAction {
Alexander Kornienko09887162014-02-27 14:28:02 +000027public:
Manuel Klimek05510652014-10-07 15:49:36 +000028 TestClangTidyAction(ClangTidyCheck &Check, ast_matchers::MatchFinder &Finder,
29 ClangTidyContext &Context)
30 : Check(Check), Finder(Finder), Context(Context) {}
Daniel Jasperd07c8402013-07-29 08:19:24 +000031
32private:
Manuel Klimek05510652014-10-07 15:49:36 +000033 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
34 StringRef File) override {
35 Context.setSourceManager(&Compiler.getSourceManager());
Aaron Ballman01cee3a2015-09-02 16:04:15 +000036 Context.setCurrentFile(File);
37 Context.setASTContext(&Compiler.getASTContext());
38
39 Check.registerMatchers(&Finder);
Alexander Kornienko09887162014-02-27 14:28:02 +000040 Check.registerPPCallbacks(Compiler);
Manuel Klimek05510652014-10-07 15:49:36 +000041 return Finder.newASTConsumer();
Alexander Kornienko09887162014-02-27 14:28:02 +000042 }
Daniel Jasperd07c8402013-07-29 08:19:24 +000043
Alexander Kornienko09887162014-02-27 14:28:02 +000044 ClangTidyCheck &Check;
Manuel Klimek05510652014-10-07 15:49:36 +000045 ast_matchers::MatchFinder &Finder;
46 ClangTidyContext &Context;
Daniel Jasperd07c8402013-07-29 08:19:24 +000047};
48
Alexander Kornienko9eb8c922014-04-08 12:27:49 +000049template <typename T>
Samuel Benzaquen462501e2015-03-31 13:53:03 +000050std::string
51runCheckOnCode(StringRef Code, std::vector<ClangTidyError> *Errors = nullptr,
52 const Twine &Filename = "input.cc",
53 ArrayRef<std::string> ExtraArgs = None,
Manuel Klimekd00d6f12015-08-11 11:37:48 +000054 const ClangTidyOptions &ExtraOptions = ClangTidyOptions(),
Manuel Klimekf6036432015-08-11 12:13:15 +000055 std::map<StringRef, StringRef> PathsToContent =
56 std::map<StringRef, StringRef>()) {
Samuel Benzaquen462501e2015-03-31 13:53:03 +000057 ClangTidyOptions Options = ExtraOptions;
Alexander Kornienkod53d2682014-09-04 14:23:36 +000058 Options.Checks = "*";
59 ClangTidyContext Context(llvm::make_unique<DefaultOptionsProvider>(
60 ClangTidyGlobalOptions(), Options));
Alexander Kornienko09887162014-02-27 14:28:02 +000061 ClangTidyDiagnosticConsumer DiagConsumer(Context);
Alexander Kornienko6e0cbc82014-09-12 08:53:36 +000062 T Check("test-check", &Context);
Manuel Klimek05510652014-10-07 15:49:36 +000063
64 std::vector<std::string> ArgCXX11(1, "clang-tidy");
65 ArgCXX11.push_back("-fsyntax-only");
66 ArgCXX11.push_back("-std=c++11");
Manuel Klimekd00d6f12015-08-11 11:37:48 +000067 ArgCXX11.push_back("-Iinclude");
Manuel Klimek05510652014-10-07 15:49:36 +000068 ArgCXX11.insert(ArgCXX11.end(), ExtraArgs.begin(), ExtraArgs.end());
69 ArgCXX11.push_back(Filename.str());
Aaron Ballman01cee3a2015-09-02 16:04:15 +000070
71 ast_matchers::MatchFinder Finder;
Manuel Klimek81593db2014-10-09 13:22:46 +000072 llvm::IntrusiveRefCntPtr<FileManager> Files(
Manuel Klimek05510652014-10-07 15:49:36 +000073 new FileManager(FileSystemOptions()));
74 tooling::ToolInvocation Invocation(
Manuel Klimek81593db2014-10-09 13:22:46 +000075 ArgCXX11, new TestClangTidyAction(Check, Finder, Context), Files.get());
76 Invocation.mapVirtualFile(Filename.str(), Code);
Manuel Klimekf6036432015-08-11 12:13:15 +000077 for (const auto &FileContent : PathsToContent) {
Manuel Klimekd00d6f12015-08-11 11:37:48 +000078 Invocation.mapVirtualFile(Twine("include/" + FileContent.first).str(),
79 FileContent.second);
80 }
Manuel Klimek05510652014-10-07 15:49:36 +000081 Invocation.setDiagnosticConsumer(&DiagConsumer);
Manuel Klimek9b2c4532015-08-12 07:57:16 +000082 if (!Invocation.run()) {
83 std::string ErrorText;
Manuel Klimek0a19e902015-08-13 09:09:28 +000084 for (const auto &Error : Context.getErrors()) {
Manuel Klimek9b2c4532015-08-12 07:57:16 +000085 ErrorText += Error.Message.Message + "\n";
86 }
87 llvm::report_fatal_error(ErrorText);
88 }
Manuel Klimek05510652014-10-07 15:49:36 +000089
Alexander Kornienko09887162014-02-27 14:28:02 +000090 DiagConsumer.finish();
91 tooling::Replacements Fixes;
Alexander Kornienko826b5ad2014-05-09 12:24:09 +000092 for (const ClangTidyError &Error : Context.getErrors())
Alexander Kornienko33a9bcc2014-04-29 15:20:10 +000093 Fixes.insert(Error.Fix.begin(), Error.Fix.end());
Alexander Kornienko826b5ad2014-05-09 12:24:09 +000094 if (Errors)
95 *Errors = Context.getErrors();
Alexander Kornienko09887162014-02-27 14:28:02 +000096 return tooling::applyAllReplacements(Code, Fixes);
97}
98
Alexander Kornienko37f80452015-03-02 11:55:04 +000099#define EXPECT_NO_CHANGES(Check, Code) \
100 EXPECT_EQ(Code, runCheckOnCode<Check>(Code))
101
Alexander Kornienko09887162014-02-27 14:28:02 +0000102} // namespace test
Daniel Jasperd07c8402013-07-29 08:19:24 +0000103} // namespace tidy
104} // namespace clang
105
Alexander Kornienko66580552015-03-09 16:52:33 +0000106#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_TIDY_CLANGTIDYTEST_H