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 ExternalDiagEngine = &Compiler.getDiagnostics(); 43 auto DiagConsumer = 44 new ClangTidyDiagnosticConsumer(*Context, ExternalDiagEngine); 45 auto DiagEngine = std::make_unique<DiagnosticsEngine>( 46 new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); 47 Context->setDiagnosticsEngine(DiagEngine.get()); 48 49 // Create the AST consumer. 50 ClangTidyASTConsumerFactory Factory(*Context); 51 std::vector<std::unique_ptr<ASTConsumer>> Vec; 52 Vec.push_back(Factory.CreateASTConsumer(Compiler, File)); 53 54 return std::make_unique<WrapConsumer>( 55 std::move(Context), std::move(DiagEngine), std::move(Vec)); 56 } 57 ParseArgs(const CompilerInstance &,const std::vector<std::string> & Args)58 bool ParseArgs(const CompilerInstance &, 59 const std::vector<std::string> &Args) override { 60 ClangTidyGlobalOptions GlobalOptions; 61 ClangTidyOptions DefaultOptions; 62 ClangTidyOptions OverrideOptions; 63 64 // Parse the extra command line args. 65 // FIXME: This is very limited at the moment. 66 for (StringRef Arg : Args) 67 if (Arg.startswith("-checks=")) 68 OverrideOptions.Checks = std::string(Arg.substr(strlen("-checks="))); 69 70 auto Options = std::make_unique<FileOptionsProvider>( 71 GlobalOptions, DefaultOptions, OverrideOptions); 72 Context = std::make_unique<ClangTidyContext>(std::move(Options)); 73 return true; 74 } 75 76 private: 77 std::unique_ptr<ClangTidyContext> Context; 78 }; 79 } // namespace tidy 80 } // namespace clang 81 82 // This anchor is used to force the linker to link in the generated object file 83 // and thus register the clang-tidy plugin. 84 volatile int ClangTidyPluginAnchorSource = 0; 85 86 static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction> 87 X("clang-tidy", "clang-tidy"); 88