18f5eb56dSBenjamin Kramer //===- ClangTidyPlugin.cpp - clang-tidy as a clang plugin -----------------===// 28f5eb56dSBenjamin Kramer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68f5eb56dSBenjamin Kramer // 78f5eb56dSBenjamin Kramer //===----------------------------------------------------------------------===// 88f5eb56dSBenjamin Kramer 98f5eb56dSBenjamin Kramer #include "../ClangTidy.h" 1060e1296aSNikolai Kosjar #include "../ClangTidyDiagnosticConsumer.h" 1137512e58SIvan Donchevskii #include "../ClangTidyForceLinker.h" 128f5eb56dSBenjamin Kramer #include "../ClangTidyModule.h" 138f5eb56dSBenjamin Kramer #include "clang/Frontend/CompilerInstance.h" 148f5eb56dSBenjamin Kramer #include "clang/Frontend/FrontendPluginRegistry.h" 158f5eb56dSBenjamin Kramer #include "clang/Frontend/MultiplexConsumer.h" 168f5eb56dSBenjamin Kramer 177d2ea6c4SCarlos Galvez namespace clang::tidy { 188f5eb56dSBenjamin Kramer 198f5eb56dSBenjamin Kramer /// The core clang tidy plugin action. This just provides the AST consumer and 208f5eb56dSBenjamin Kramer /// command line flag parsing for using clang-tidy as a clang plugin. 218f5eb56dSBenjamin Kramer class ClangTidyPluginAction : public PluginASTAction { 2260e1296aSNikolai Kosjar /// Wrapper to grant the context and diagnostics engine the same lifetime as 2360e1296aSNikolai Kosjar /// the action. 2460e1296aSNikolai Kosjar /// We use MultiplexConsumer to avoid writing out all the forwarding methods. 258f5eb56dSBenjamin Kramer class WrapConsumer : public MultiplexConsumer { 268f5eb56dSBenjamin Kramer std::unique_ptr<ClangTidyContext> Context; 2760e1296aSNikolai Kosjar std::unique_ptr<DiagnosticsEngine> DiagEngine; 288f5eb56dSBenjamin Kramer 298f5eb56dSBenjamin Kramer public: WrapConsumer(std::unique_ptr<ClangTidyContext> Context,std::unique_ptr<DiagnosticsEngine> DiagEngine,std::vector<std::unique_ptr<ASTConsumer>> Consumer)308f5eb56dSBenjamin Kramer WrapConsumer(std::unique_ptr<ClangTidyContext> Context, 3160e1296aSNikolai Kosjar std::unique_ptr<DiagnosticsEngine> DiagEngine, 328f5eb56dSBenjamin Kramer std::vector<std::unique_ptr<ASTConsumer>> Consumer) 3360e1296aSNikolai Kosjar : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)), 3460e1296aSNikolai Kosjar DiagEngine(std::move(DiagEngine)) {} 358f5eb56dSBenjamin Kramer }; 368f5eb56dSBenjamin Kramer 378f5eb56dSBenjamin Kramer public: CreateASTConsumer(CompilerInstance & Compiler,StringRef File)388f5eb56dSBenjamin Kramer std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 398f5eb56dSBenjamin Kramer StringRef File) override { 4060e1296aSNikolai Kosjar // Create and set diagnostics engine 41ab2d3ce4SAlexander Kornienko auto *DiagConsumer = 42ab2d3ce4SAlexander Kornienko new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics()); 431c705d9cSJonas Devlieghere auto DiagEngine = std::make_unique<DiagnosticsEngine>( 4460e1296aSNikolai Kosjar new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); 4560e1296aSNikolai Kosjar Context->setDiagnosticsEngine(DiagEngine.get()); 468f5eb56dSBenjamin Kramer 478f5eb56dSBenjamin Kramer // Create the AST consumer. 488f5eb56dSBenjamin Kramer ClangTidyASTConsumerFactory Factory(*Context); 498f5eb56dSBenjamin Kramer std::vector<std::unique_ptr<ASTConsumer>> Vec; 50ade0662cSSalman Javed Vec.push_back(Factory.createASTConsumer(Compiler, File)); 518f5eb56dSBenjamin Kramer 521c705d9cSJonas Devlieghere return std::make_unique<WrapConsumer>( 5360e1296aSNikolai Kosjar std::move(Context), std::move(DiagEngine), std::move(Vec)); 548f5eb56dSBenjamin Kramer } 558f5eb56dSBenjamin Kramer ParseArgs(const CompilerInstance &,const std::vector<std::string> & Args)568f5eb56dSBenjamin Kramer bool ParseArgs(const CompilerInstance &, 578f5eb56dSBenjamin Kramer const std::vector<std::string> &Args) override { 588f5eb56dSBenjamin Kramer ClangTidyGlobalOptions GlobalOptions; 598f5eb56dSBenjamin Kramer ClangTidyOptions DefaultOptions; 608f5eb56dSBenjamin Kramer ClangTidyOptions OverrideOptions; 618f5eb56dSBenjamin Kramer 628f5eb56dSBenjamin Kramer // Parse the extra command line args. 638f5eb56dSBenjamin Kramer // FIXME: This is very limited at the moment. 648f5eb56dSBenjamin Kramer for (StringRef Arg : Args) 65*76bbbcb4SKazu Hirata if (Arg.starts_with("-checks=")) 66adcd0268SBenjamin Kramer OverrideOptions.Checks = std::string(Arg.substr(strlen("-checks="))); 678f5eb56dSBenjamin Kramer 681c705d9cSJonas Devlieghere auto Options = std::make_unique<FileOptionsProvider>( 698f5eb56dSBenjamin Kramer GlobalOptions, DefaultOptions, OverrideOptions); 701c705d9cSJonas Devlieghere Context = std::make_unique<ClangTidyContext>(std::move(Options)); 718f5eb56dSBenjamin Kramer return true; 728f5eb56dSBenjamin Kramer } 738f5eb56dSBenjamin Kramer 748f5eb56dSBenjamin Kramer private: 758f5eb56dSBenjamin Kramer std::unique_ptr<ClangTidyContext> Context; 768f5eb56dSBenjamin Kramer }; 777d2ea6c4SCarlos Galvez } // namespace clang::tidy 788f5eb56dSBenjamin Kramer 798f5eb56dSBenjamin Kramer // This anchor is used to force the linker to link in the generated object file 808f5eb56dSBenjamin Kramer // and thus register the clang-tidy plugin. 818f5eb56dSBenjamin Kramer volatile int ClangTidyPluginAnchorSource = 0; 828f5eb56dSBenjamin Kramer 838f5eb56dSBenjamin Kramer static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction> 848f5eb56dSBenjamin Kramer X("clang-tidy", "clang-tidy"); 85