86 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "../ClangTidy.h"10#include "../ClangTidyDiagnosticConsumer.h"11#include "../ClangTidyModule.h"12#include "clang/Frontend/CompilerInstance.h"13#include "clang/Frontend/FrontendPluginRegistry.h"14#include "clang/Frontend/MultiplexConsumer.h"15 16namespace clang::tidy {17 18/// The core clang tidy plugin action. This just provides the AST consumer and19/// command line flag parsing for using clang-tidy as a clang plugin.20class ClangTidyPluginAction : public PluginASTAction {21 /// Wrapper to grant the context and diagnostics engine the same lifetime as22 /// the action.23 /// We use MultiplexConsumer to avoid writing out all the forwarding methods.24 class WrapConsumer : public MultiplexConsumer {25 std::unique_ptr<ClangTidyContext> Context;26 std::unique_ptr<DiagnosticsEngine> DiagEngine;27 28 public:29 WrapConsumer(std::unique_ptr<ClangTidyContext> Context,30 std::unique_ptr<DiagnosticsEngine> DiagEngine,31 std::vector<std::unique_ptr<ASTConsumer>> Consumer)32 : MultiplexConsumer(std::move(Consumer)), Context(std::move(Context)),33 DiagEngine(std::move(DiagEngine)) {}34 };35 36public:37 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,38 StringRef File) override {39 // Create and set diagnostics engine40 auto *DiagConsumer =41 new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics());42 auto DiagOpts = std::make_unique<DiagnosticOptions>();43 auto DiagEngine = std::make_unique<DiagnosticsEngine>(44 DiagnosticIDs::create(), *DiagOpts, DiagConsumer);45 Context->setDiagnosticsEngine(std::move(DiagOpts), 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 56 bool ParseArgs(const CompilerInstance &,57 const std::vector<std::string> &Args) override {58 const ClangTidyGlobalOptions GlobalOptions;59 const ClangTidyOptions DefaultOptions;60 ClangTidyOptions OverrideOptions;61 62 // Parse the extra command line args.63 // FIXME: This is very limited at the moment.64 for (const 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 74private:75 std::unique_ptr<ClangTidyContext> Context;76};77} // namespace clang::tidy78 79// This anchor is used to force the linker to link in the generated object file80// and thus register the clang-tidy plugin.81// NOLINTNEXTLINE(misc-use-internal-linkage)82volatile int ClangTidyPluginAnchorSource = 0;83 84static clang::FrontendPluginRegistry::Add<clang::tidy::ClangTidyPluginAction>85 X("clang-tidy", "clang-tidy");86