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