10 #include "clang/Lex/Preprocessor.h"
11 #include "llvm/ADT/STLExtras.h"
16 using transformer::RewriteRule;
20 return C.Explanation !=
nullptr;
30 std::function<Optional<RewriteRule>(
const LangOptions &,
35 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
36 IncludeSorter::IS_LLVM)) {
39 "clang-tidy checks must have an explanation by default;"
40 " explicitly provide an empty explanation if none is desired");
43 TransformerClangTidyCheck::TransformerClangTidyCheck(RewriteRule R,
45 ClangTidyContext *Context)
46 : ClangTidyCheck(
Name, Context), Rule(std::move(R)),
47 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
48 IncludeSorter::IS_LLVM)) {
50 "clang-tidy checks must have an explanation by default;"
51 " explicitly provide an empty explanation if none is desired");
54 void TransformerClangTidyCheck::registerPPCallbacks(
55 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
58 if (Rule && llvm::any_of(Rule->Cases, [](
const RewriteRule::Case &C) {
59 return !C.AddedIncludes.empty();
62 std::make_unique<IncludeInserter>(SM, getLangOpts(), IncludeStyle);
63 PP->addPPCallbacks(Inserter->CreatePPCallbacks());
67 void TransformerClangTidyCheck::registerMatchers(
68 ast_matchers::MatchFinder *Finder) {
70 for (
auto &Matcher : transformer::detail::buildMatchers(*Rule))
71 Finder->addDynamicMatcher(Matcher,
this);
74 void TransformerClangTidyCheck::check(
75 const ast_matchers::MatchFinder::MatchResult &Result) {
76 if (Result.Context->getDiagnostics().hasErrorOccurred())
79 assert(Rule &&
"check() should not fire if Rule is None");
80 RewriteRule::Case Case = transformer::detail::findSelectedCase(Result, *Rule);
81 Expected<SmallVector<transformer::Edit, 1>> Edits = Case.Edits(Result);
83 llvm::errs() <<
"Rewrite failed: " <<
llvm::toString(Edits.takeError())
92 Expected<std::string> Explanation = Case.Explanation->eval(Result);
94 llvm::errs() <<
"Error in explanation: "
100 DiagnosticBuilder Diag = diag((*Edits)[0].
Range.getBegin(), *Explanation);
101 for (
const auto &T : *Edits)
102 Diag << FixItHint::CreateReplacement(T.Range, T.Replacement);
104 for (
const auto &I : Case.AddedIncludes) {
105 Diag << Inserter->CreateIncludeInsertion(
106 Result.SourceManager->getMainFileID(), I.first,
107 I.second == transformer::IncludeFormat::Angled);
111 void TransformerClangTidyCheck::storeOptions(
113 Options.store(Opts,
"IncludeStyle", IncludeStyle);