10#include "clang/Basic/DiagnosticIDs.h"
11#include "clang/Lex/Preprocessor.h"
15using transformer::RewriteRuleWith;
18static bool hasGenerator(
const transformer::Generator<std::string> &G) {
23static void verifyRule(
const RewriteRuleWith<std::string> &Rule) {
25 "clang-tidy checks must have an explanation by default;"
26 " explicitly provide an empty explanation if none is desired");
35 auto Pos = ToEscape.find(
'%');
36 if (Pos == std::string::npos)
40 Result.reserve(ToEscape.size());
43 Result.append(ToEscape, 0, Pos);
46 for (
auto N = ToEscape.size(); Pos < N; ++Pos) {
47 const char C = ToEscape.at(Pos);
59 Inserter(Options.getLocalOrGlobal(
"IncludeStyle",
IncludeSorter::IS_LLVM),
60 areDiagsSelfContained()) {}
68 llvm::function_ref<std::optional<RewriteRuleWith<std::string>>(
69 const LangOptions &,
const OptionsView &)>
73 if (std::optional<RewriteRuleWith<std::string>> R =
74 MakeRule(getLangOpts(), Options))
80 : TransformerClangTidyCheck(Name, Context) {
85 transformer::RewriteRuleWith<std::string> R) {
91 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
92 Inserter.registerPreprocessor(PP);
96 ast_matchers::MatchFinder *Finder) {
97 if (!Rule.Cases.empty())
98 for (
auto &Matcher : transformer::detail::buildMatchers(Rule))
99 Finder->addDynamicMatcher(Matcher,
this);
103 const ast_matchers::MatchFinder::MatchResult &Result) {
104 if (Result.Context->getDiagnostics().hasErrorOccurred())
107 const size_t I = transformer::detail::findSelectedCase(Result, Rule);
108 Expected<SmallVector<transformer::Edit, 1>> Edits =
109 Rule.Cases[I].Edits(Result);
111 llvm::errs() <<
"Rewrite failed: " << llvm::toString(Edits.takeError())
120 Expected<std::string> Explanation = Rule.Metadata[I]->eval(Result);
122 llvm::errs() <<
"Error in explanation: "
123 << llvm::toString(Explanation.takeError()) <<
"\n";
129 const DiagnosticBuilder Diag =
131 for (
const auto &T : *Edits) {
133 case transformer::EditKind::Range:
134 Diag << FixItHint::CreateReplacement(T.Range, T.Replacement);
136 case transformer::EditKind::AddInclude:
137 Diag << Inserter.createIncludeInsertion(
138 Result.SourceManager->getFileID(T.Range.getBegin()), T.Replacement);
144 for (
const auto &T : *Edits) {
145 if (!T.Note.empty()) {
147 DiagnosticIDs::Note);
154 Options.store(Opts,
"IncludeStyle", Inserter.getStyle());
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
static bool hasGenerator(const transformer::Generator< std::string > &G)
static void verifyRule(const RewriteRuleWith< std::string > &Rule)
IncludeSorter(const SourceManager *SourceMgr, FileID FileID, StringRef FileName, IncludeStyle Style)
Class used by IncludeInserterCallback to record the names of the / inclusions in a given source file ...
static std::string escapeForDiagnostic(std::string ToEscape)
llvm::StringMap< ClangTidyValue > OptionMap