//===- ClangTidyPlugin.cpp - clang-tidy as a clang plugin -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "../ClangTidy.h" #include "../ClangTidyDiagnosticConsumer.h" #include "../ClangTidyForceLinker.h" #include "../ClangTidyModule.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/MultiplexConsumer.h" namespace clang { namespace tidy { /// The core clang tidy plugin action. This just provides the AST consumer and /// command line flag parsing for using clang-tidy as a clang plugin. class ClangTidyPluginAction : public PluginASTAction { /// Wrapper to grant the context and diagnostics engine the same lifetime as /// the action. /// We use MultiplexConsumer to avoid writing out all the forwarding methods. class WrapConsumer : public MultiplexConsumer { std::unique_ptr Context; std::unique_ptr DiagEngine; public: WrapConsumer(std::unique_ptr Context, std::unique_ptr DiagEngine, std::vector> Consumer) : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)), DiagEngine(std::move(DiagEngine)) {} }; public: std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, StringRef File) override { // Create and set diagnostics engine auto ExternalDiagEngine = &Compiler.getDiagnostics(); auto DiagConsumer = new ClangTidyDiagnosticConsumer(*Context, ExternalDiagEngine); auto DiagEngine = std::make_unique( new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); Context->setDiagnosticsEngine(DiagEngine.get()); // Create the AST consumer. ClangTidyASTConsumerFactory Factory(*Context); std::vector> Vec; Vec.push_back(Factory.CreateASTConsumer(Compiler, File)); return std::make_unique( std::move(Context), std::move(DiagEngine), std::move(Vec)); } bool ParseArgs(const CompilerInstance &, const std::vector &Args) override { ClangTidyGlobalOptions GlobalOptions; ClangTidyOptions DefaultOptions; ClangTidyOptions OverrideOptions; // Parse the extra command line args. // FIXME: This is very limited at the moment. for (StringRef Arg : Args) if (Arg.startswith("-checks=")) OverrideOptions.Checks = std::string(Arg.substr(strlen("-checks="))); auto Options = std::make_unique( GlobalOptions, DefaultOptions, OverrideOptions); Context = std::make_unique(std::move(Options)); return true; } private: std::unique_ptr Context; }; } // namespace tidy } // namespace clang // This anchor is used to force the linker to link in the generated object file // and thus register the clang-tidy plugin. volatile int ClangTidyPluginAnchorSource = 0; static clang::FrontendPluginRegistry::Add X("clang-tidy", "clang-tidy");