1 //===- ClangTidyPlugin.cpp - clang-tidy as a clang plugin -----------------===// 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 9 #include "../ClangTidy.h" 10 #include "../ClangTidyDiagnosticConsumer.h" 11 #include "../ClangTidyForceLinker.h" 12 #include "../ClangTidyModule.h" 13 #include "clang/Frontend/CompilerInstance.h" 14 #include "clang/Frontend/FrontendPluginRegistry.h" 15 #include "clang/Frontend/MultiplexConsumer.h" 16 17 namespace clang { 18 namespace tidy { 19 20 /// The core clang tidy plugin action. This just provides the AST consumer and 21 /// command line flag parsing for using clang-tidy as a clang plugin. 22 class ClangTidyPluginAction : public PluginASTAction { 23 /// Wrapper to grant the context and diagnostics engine the same lifetime as 24 /// the action. 25 /// We use MultiplexConsumer to avoid writing out all the forwarding methods. 26 class WrapConsumer : public MultiplexConsumer { 27 std::unique_ptr<ClangTidyContext> Context; 28 std::unique_ptr<DiagnosticsEngine> DiagEngine; 29 30 public: WrapConsumer(std::unique_ptr<ClangTidyContext> Context,std::unique_ptr<DiagnosticsEngine> DiagEngine,std::vector<std::unique_ptr<ASTConsumer>> Consumer)31 WrapConsumer(std::unique_ptr<ClangTidyContext> Context, 32 std::unique_ptr<DiagnosticsEngine> DiagEngine, 33 std::vector<std::unique_ptr<ASTConsumer>> Consumer) 34 : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)), 35 DiagEngine(std::move(DiagEngine)) {} 36 }; 37 38 public: CreateASTConsumer(CompilerInstance & Compiler,StringRef File)39 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 40 StringRef File) override { 41 // Create and set diagnostics engine 42 auto *DiagConsumer = 43 new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics()); 44 auto DiagEngine = std::make_unique<DiagnosticsEngine>( 45 new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); 46 Context->setDiagnosticsEngine(DiagEngine.get()); 47 48 // Create the AST consumer. 49 ClangTidyASTConsumerFactory Factory(*Context); 50 std::vector<std::unique_ptr<ASTConsumer>> Vec; 51 Vec.push_back(Factory.createASTConsumer(Compiler, File)); 52 53 return std::make_unique<WrapConsumer>( 54 std::move(Context), std::move(DiagEngine), std::move(Vec)); 55 } 56 ParseArgs(const CompilerInstance &,const std::vector<std::string> & Args)57 bool ParseArgs(const CompilerInstance &, 58 const std::vector<std::string> &Args) override { 59 ClangTidyGlobalOptions GlobalOptions; 60 ClangTidyOptions DefaultOptions; 61 ClangTidyOptions OverrideOptions; 62 63 // Parse the extra command line args. 64 // FIXME: This is very limited at the moment. 65 for (StringRef Arg : Args) 66 if (Arg.startswith("-checks=")) 67 OverrideOptions.Checks = std::string(Arg.substr(strlen("-checks="))); 68 69 auto Options = std::make_unique<FileOptionsProvider>( 70 GlobalOptions, DefaultOptions, OverrideOptions); 71 Context = std::make_unique<ClangTidyContext>(std::move(Options)); 72 return true; 73 } 74 75 private: 76 std::unique_ptr<ClangTidyContext> Context; 77 }; 78 } // namespace tidy 79 } // namespace clang 80 81 // This anchor is used to force the linker to link in the generated object file 82 // and thus register the clang-tidy plugin. 83 volatile int ClangTidyPluginAnchorSource = 0; 84 85 static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction> 86 X("clang-tidy", "clang-tidy"); 87