xref: /llvm-project/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp (revision 76bbbcb41bcf4a1d7a26bb11b78cf97b60ea7d4b)
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