//===- 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<ClangTidyContext> Context; std::unique_ptr<DiagnosticsEngine> DiagEngine; public: WrapConsumer(std::unique_ptr<ClangTidyContext> Context, std::unique_ptr<DiagnosticsEngine> DiagEngine, std::vector<std::unique_ptr<ASTConsumer>> Consumer) : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)), DiagEngine(std::move(DiagEngine)) {} }; public: std::unique_ptr<ASTConsumer> 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<DiagnosticsEngine>( new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); Context->setDiagnosticsEngine(DiagEngine.get()); // Create the AST consumer. ClangTidyASTConsumerFactory Factory(*Context); std::vector<std::unique_ptr<ASTConsumer>> Vec; Vec.push_back(Factory.CreateASTConsumer(Compiler, File)); return std::make_unique<WrapConsumer>( std::move(Context), std::move(DiagEngine), std::move(Vec)); } bool ParseArgs(const CompilerInstance &, const std::vector<std::string> &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 = Arg.substr(strlen("-checks=")); auto Options = std::make_unique<FileOptionsProvider>( GlobalOptions, DefaultOptions, OverrideOptions); Context = std::make_unique<ClangTidyContext>(std::move(Options)); return true; } private: std::unique_ptr<ClangTidyContext> 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<clang::tidy::ClangTidyPluginAction> X("clang-tidy", "clang-tidy");