22#include "clang/AST/ASTContext.h"
23#include "clang/AST/ASTDiagnostic.h"
24#include "clang/AST/Attr.h"
25#include "clang/Basic/CharInfo.h"
26#include "clang/Basic/Diagnostic.h"
27#include "clang/Basic/DiagnosticOptions.h"
28#include "clang/Basic/FileManager.h"
29#include "clang/Basic/SourceManager.h"
30#include "clang/Frontend/DiagnosticRenderer.h"
31#include "clang/Lex/Lexer.h"
32#include "clang/Tooling/Core/Diagnostic.h"
33#include "clang/Tooling/Core/Replacement.h"
34#include "llvm/ADT/BitVector.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/StringMap.h"
38#include "llvm/Support/FormatVariadic.h"
39#include "llvm/Support/Regex.h"
48class ClangTidyDiagnosticRenderer :
public DiagnosticRenderer {
50 ClangTidyDiagnosticRenderer(
const LangOptions &LangOpts,
51 DiagnosticOptions *DiagOpts,
53 : DiagnosticRenderer(LangOpts, DiagOpts),
Error(
Error) {}
56 void emitDiagnosticMessage(FullSourceLoc
Loc, PresumedLoc PLoc,
57 DiagnosticsEngine::Level Level, StringRef Message,
58 ArrayRef<CharSourceRange> Ranges,
59 DiagOrStoredDiag
Info)
override {
64 std::string CheckNameInMessage =
" [" +
Error.DiagnosticName +
"]";
65 Message.consume_back(CheckNameInMessage);
69 ? tooling::DiagnosticMessage(Message,
Loc.getManager(),
Loc)
70 : tooling::DiagnosticMessage(
Message);
76 auto ToCharRange = [
this, &
Loc](
const CharSourceRange &SourceRange) {
77 if (SourceRange.isCharRange())
79 assert(SourceRange.isTokenRange());
80 SourceLocation End = Lexer::getLocForEndOfToken(
81 SourceRange.getEnd(), 0,
Loc.getManager(), LangOpts);
82 return CharSourceRange::getCharRange(SourceRange.getBegin(), End);
87 llvm::make_filter_range(Ranges, [](
const CharSourceRange &R) {
88 return R.getAsRange().isValid();
91 if (Level == DiagnosticsEngine::Note) {
92 Error.Notes.push_back(TidyMessage);
93 for (
const CharSourceRange &SourceRange : ValidRanges)
94 Error.Notes.back().Ranges.emplace_back(
Loc.getManager(),
95 ToCharRange(SourceRange));
98 assert(
Error.Message.Message.empty() &&
"Overwriting a diagnostic message");
99 Error.Message = TidyMessage;
100 for (
const CharSourceRange &SourceRange : ValidRanges)
101 Error.Message.Ranges.emplace_back(
Loc.getManager(),
102 ToCharRange(SourceRange));
105 void emitDiagnosticLoc(FullSourceLoc
Loc, PresumedLoc PLoc,
106 DiagnosticsEngine::Level Level,
107 ArrayRef<CharSourceRange> Ranges)
override {}
109 void emitCodeContext(FullSourceLoc
Loc, DiagnosticsEngine::Level Level,
110 SmallVectorImpl<CharSourceRange> &Ranges,
111 ArrayRef<FixItHint>
Hints)
override {
112 assert(
Loc.isValid());
113 tooling::DiagnosticMessage *DiagWithFix =
114 Level == DiagnosticsEngine::Note ? &
Error.Notes.back() : &
Error.Message;
118 assert(
Range.getBegin().isValid() &&
Range.getEnd().isValid() &&
119 "Invalid range in the fix-it hint.");
120 assert(
Range.getBegin().isFileID() &&
Range.getEnd().isFileID() &&
121 "Only file locations supported in fix-it hints.");
123 tooling::Replacement Replacement(
Loc.getManager(), Range,
126 DiagWithFix->Fix[Replacement.getFilePath()].add(Replacement);
130 llvm::errs() <<
"Fix conflicts with existing fix! "
131 << llvm::toString(std::move(Err)) <<
"\n";
132 assert(
false &&
"Fix conflicts with existing fix!");
137 void emitIncludeLocation(FullSourceLoc
Loc, PresumedLoc PLoc)
override {}
139 void emitImportLocation(FullSourceLoc
Loc, PresumedLoc PLoc,
140 StringRef ModuleName)
override {}
142 void emitBuildingModuleLocation(FullSourceLoc
Loc, PresumedLoc PLoc,
143 StringRef ModuleName)
override {}
145 void endDiagnostic(DiagOrStoredDiag D,
146 DiagnosticsEngine::Level Level)
override {
147 assert(!
Error.Message.Message.empty() &&
"Message has not been set");
156 ClangTidyError::Level DiagLevel,
157 StringRef BuildDirectory,
bool IsWarningAsError)
158 : tooling::
Diagnostic(CheckName, DiagLevel, BuildDirectory),
159 IsWarningAsError(IsWarningAsError) {}
162 std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
164 : OptionsProvider(std::move(OptionsProvider)),
176 StringRef CheckName, SourceLocation
Loc, StringRef Description,
177 DiagnosticIDs::Level Level ) {
178 assert(
Loc.isValid());
179 unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
180 Level, (Description +
" [" + CheckName +
"]").str());
181 CheckNamesByDiagnosticID.try_emplace(
ID, CheckName);
182 return DiagEngine->Report(
Loc,
ID);
186 StringRef CheckName, StringRef Description,
187 DiagnosticIDs::Level Level ) {
188 unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
189 Level, (Description +
" [" + CheckName +
"]").str());
190 CheckNamesByDiagnosticID.try_emplace(
ID, CheckName);
191 return DiagEngine->Report(
ID);
195 SourceManager &SM = DiagEngine->getSourceManager();
196 FileManager &FM = SM.getFileManager();
197 FileEntryRef File = llvm::cantFail(FM.getFileRef(
Error.Message.FilePath));
198 FileID
ID = SM.getOrCreateFileID(File, SrcMgr::C_User);
199 SourceLocation FileStartLoc = SM.getLocForStartOfFile(
ID);
200 SourceLocation
Loc = FileStartLoc.getLocWithOffset(
201 static_cast<SourceLocation::IntTy
>(
Error.Message.FileOffset));
203 static_cast<DiagnosticIDs::Level
>(
Error.DiagLevel));
208 DiagnosticIDs::Level Level ) {
209 return diag(
"clang-tidy-config", Message, Level);
214 SmallVectorImpl<tooling::Diagnostic> &NoLintErrors,
bool AllowIO,
215 bool EnableNoLintBlocks) {
218 AllowIO, EnableNoLintBlocks);
222 DiagEngine->setSourceManager(SourceMgr);
227 FileExtensions.clear();
228 for (StringRef
Suffix : AllFileExtensions) {
229 StringRef Extension =
Suffix.trim();
230 if (!llvm::all_of(Extension, isAlphanumeric))
232 FileExtensions.insert(Extension);
238 CurrentFile = std::string(File);
240 CheckFilter = std::make_unique<CachedGlobList>(*
getOptions().Checks);
241 WarningAsErrorFilter =
242 std::make_unique<CachedGlobList>(*
getOptions().WarningsAsErrors);
244 HeaderFileExtensions))
247 ImplementationFileExtensions))
252 DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);
253 LangOpts = Context->getLangOpts();
257 return OptionsProvider->getGlobalOptions();
261 return CurrentOptions;
268 OptionsProvider->getOptions(File), 0);
274 ProfilePrefix = std::string(Prefix);
277std::optional<ClangTidyProfiling::StorageParams>
279 if (ProfilePrefix.empty())
286 assert(CheckFilter !=
nullptr);
287 return CheckFilter->contains(CheckName);
291 assert(WarningAsErrorFilter !=
nullptr);
292 return WarningAsErrorFilter->contains(CheckName);
296 std::string ClangWarningOption = std::string(
297 DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(DiagnosticID));
298 if (!ClangWarningOption.empty())
299 return "clang-diagnostic-" + ClangWarningOption;
300 llvm::DenseMap<unsigned, std::string>::const_iterator I =
301 CheckNamesByDiagnosticID.find(DiagnosticID);
302 if (I != CheckNamesByDiagnosticID.end())
309 bool RemoveIncompatibleErrors,
bool GetFixesFromNotes,
310 bool EnableNolintBlocks)
311 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
312 RemoveIncompatibleErrors(RemoveIncompatibleErrors),
313 GetFixesFromNotes(GetFixesFromNotes),
314 EnableNolintBlocks(EnableNolintBlocks) {}
316void ClangTidyDiagnosticConsumer::finalizeLastError() {
317 if (!Errors.empty()) {
319 if (
Error.DiagnosticName ==
"clang-tidy-config") {
322 Error.DiagLevel != ClangTidyError::Error) {
325 }
else if (!LastErrorRelatesToUserCode) {
328 }
else if (!LastErrorPassesLineFilter) {
335 LastErrorRelatesToUserCode =
false;
336 LastErrorPassesLineFilter =
false;
341const llvm::StringMap<tooling::Replacements> *
347 const llvm::StringMap<tooling::Replacements> *Result =
nullptr;
349 if (!Note.Fix.empty()) {
363 if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
366 SmallVector<tooling::Diagnostic, 1> SuppressionErrors;
368 EnableNolintBlocks)) {
371 LastErrorWasIgnored =
true;
372 Context.DiagEngine->Clear();
373 for (
const auto &
Error : SuppressionErrors)
378 LastErrorWasIgnored =
false;
380 DiagnosticConsumer::HandleDiagnostic(DiagLevel,
Info);
382 if (DiagLevel == DiagnosticsEngine::Note) {
383 assert(!Errors.empty() &&
384 "A diagnostic note can only be appended to a message.");
388 if (CheckName.empty()) {
392 case DiagnosticsEngine::Error:
393 case DiagnosticsEngine::Fatal:
394 CheckName =
"clang-diagnostic-error";
396 case DiagnosticsEngine::Warning:
397 CheckName =
"clang-diagnostic-warning";
399 case DiagnosticsEngine::Remark:
400 CheckName =
"clang-diagnostic-remark";
403 CheckName =
"clang-diagnostic-unknown";
408 ClangTidyError::Level Level = ClangTidyError::Warning;
409 if (DiagLevel == DiagnosticsEngine::Error ||
410 DiagLevel == DiagnosticsEngine::Fatal) {
413 Level = ClangTidyError::Error;
414 LastErrorRelatesToUserCode =
true;
415 LastErrorPassesLineFilter =
true;
416 }
else if (DiagLevel == DiagnosticsEngine::Remark) {
417 Level = ClangTidyError::Remark;
420 bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning &&
426 if (ExternalDiagEngine) {
429 forwardDiagnostic(
Info);
431 ClangTidyDiagnosticRenderer Converter(
432 Context.
getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),
434 SmallString<100> Message;
435 Info.FormatDiagnostic(Message);
437 if (
Info.hasSourceManager())
438 Loc = FullSourceLoc(
Info.getLocation(),
Info.getSourceManager());
439 else if (Context.DiagEngine->hasSourceManager())
440 Loc = FullSourceLoc(
Info.getLocation(),
441 Context.DiagEngine->getSourceManager());
442 Converter.emitDiagnostic(
Loc, DiagLevel, Message,
Info.getRanges(),
443 Info.getFixItHints());
446 if (
Info.hasSourceManager())
447 checkFilters(
Info.getLocation(),
Info.getSourceManager());
449 Context.DiagEngine->Clear();
450 for (
const auto &
Error : SuppressionErrors)
454bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef
FileName,
455 unsigned LineNumber)
const {
459 if (
FileName.ends_with(Filter.Name)) {
460 if (Filter.LineRanges.empty())
463 if (
Range.first <= LineNumber && LineNumber <=
Range.second)
472void ClangTidyDiagnosticConsumer::forwardDiagnostic(
const Diagnostic &
Info) {
474 auto DiagLevelAndFormatString =
476 unsigned ExternalID = ExternalDiagEngine->getDiagnosticIDs()->getCustomDiagID(
477 DiagLevelAndFormatString.first, DiagLevelAndFormatString.second);
480 auto Builder = ExternalDiagEngine->Report(
Info.getLocation(), ExternalID);
481 for (
const FixItHint &Hint :
Info.getFixItHints())
483 for (
auto Range :
Info.getRanges())
485 for (
unsigned Index = 0; Index <
Info.getNumArgs(); ++Index) {
486 DiagnosticsEngine::ArgumentKind
Kind =
Info.getArgKind(Index);
488 case clang::DiagnosticsEngine::ak_std_string:
491 case clang::DiagnosticsEngine::ak_c_string:
494 case clang::DiagnosticsEngine::ak_sint:
497 case clang::DiagnosticsEngine::ak_uint:
500 case clang::DiagnosticsEngine::ak_tokenkind:
501 Builder << static_cast<tok::TokenKind>(
Info.getRawArg(Index));
503 case clang::DiagnosticsEngine::ak_identifierinfo:
506 case clang::DiagnosticsEngine::ak_qual:
507 Builder << Qualifiers::fromOpaqueValue(
Info.getRawArg(Index));
509 case clang::DiagnosticsEngine::ak_qualtype:
510 Builder << QualType::getFromOpaquePtr((
void *)
Info.getRawArg(Index));
512 case clang::DiagnosticsEngine::ak_declarationname:
513 Builder << DeclarationName::getFromOpaqueInteger(
Info.getRawArg(Index));
515 case clang::DiagnosticsEngine::ak_nameddecl:
516 Builder << reinterpret_cast<const NamedDecl *>(
Info.getRawArg(Index));
518 case clang::DiagnosticsEngine::ak_nestednamespec:
519 Builder << reinterpret_cast<NestedNameSpecifier *>(
Info.getRawArg(Index));
521 case clang::DiagnosticsEngine::ak_declcontext:
522 Builder << reinterpret_cast<DeclContext *>(
Info.getRawArg(Index));
524 case clang::DiagnosticsEngine::ak_qualtype_pair:
527 case clang::DiagnosticsEngine::ak_attr:
528 Builder << reinterpret_cast<Attr *>(
Info.getRawArg(Index));
530 case clang::DiagnosticsEngine::ak_addrspace:
531 Builder << static_cast<LangAS>(
Info.getRawArg(Index));
537void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation
Location,
538 const SourceManager &Sources) {
541 LastErrorRelatesToUserCode =
true;
542 LastErrorPassesLineFilter =
true;
553 FileID FID = Sources.getDecomposedExpansionLoc(
Location).first;
554 OptionalFileEntryRef File = Sources.getFileEntryRefForID(FID);
559 LastErrorRelatesToUserCode =
true;
560 LastErrorPassesLineFilter =
true;
564 StringRef
FileName(File->getName());
565 LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
569 unsigned LineNumber = Sources.getExpansionLineNumber(
Location);
570 LastErrorPassesLineFilter =
571 LastErrorPassesLineFilter || passesLineFilter(
FileName, LineNumber);
574llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
578 return HeaderFilter.get();
581void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
598 Event(
unsigned Begin,
unsigned End, EventType
Type,
unsigned ErrorId,
628 Priority = std::make_tuple(Begin,
Type, -End, -ErrorSize, ErrorId);
631 Priority = std::make_tuple(Begin,
Type, -End, ErrorSize, ErrorId);
634 Priority = std::make_tuple(End,
Type, -Begin, ErrorSize, ErrorId);
639 bool operator<(
const Event &Other)
const {
640 return Priority < Other.Priority;
649 std::tuple<unsigned, EventType, int, int, unsigned> Priority;
652 removeDuplicatedDiagnosticsOfAliasCheckers();
655 std::vector<int> Sizes;
657 std::pair<ClangTidyError *, llvm::StringMap<tooling::Replacements> *>>
659 for (
auto &
Error : Errors) {
661 ErrorFixes.emplace_back(
662 &
Error,
const_cast<llvm::StringMap<tooling::Replacements> *
>(
Fix));
664 for (
const auto &ErrorAndFix : ErrorFixes) {
666 for (
const auto &FileAndReplaces : *ErrorAndFix.second) {
667 for (
const auto &Replace : FileAndReplaces.second)
668 Size += Replace.getLength();
670 Sizes.push_back(Size);
674 llvm::StringMap<std::vector<Event>> FileEvents;
675 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
676 for (
const auto &FileAndReplace : *ErrorFixes[I].second) {
677 for (
const auto &Replace : FileAndReplace.second) {
678 unsigned Begin = Replace.getOffset();
679 unsigned End = Begin + Replace.getLength();
680 auto &Events = FileEvents[Replace.getFilePath()];
682 Events.emplace_back(Begin, End, Event::ET_Insert, I, Sizes[I]);
684 Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);
685 Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);
691 llvm::BitVector
Apply(ErrorFixes.size(),
true);
692 for (
auto &FileAndEvents : FileEvents) {
693 std::vector<Event> &Events = FileAndEvents.second;
696 int OpenIntervals = 0;
697 for (
const auto &Event : Events) {
698 switch (
Event.Type) {
699 case Event::ET_Begin:
700 if (OpenIntervals++ != 0)
703 case Event::ET_Insert:
704 if (OpenIntervals != 0)
708 if (--OpenIntervals != 0)
713 assert(OpenIntervals == 0 &&
"Amount of begin/end points doesn't match");
716 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
718 ErrorFixes[I].second->clear();
719 ErrorFixes[I].first->Notes.emplace_back(
720 "this fix will not be applied because it overlaps with another fix");
726struct LessClangTidyError {
728 const tooling::DiagnosticMessage &M1 = LHS.Message;
729 const tooling::DiagnosticMessage &M2 = RHS.Message;
731 return std::tie(M1.FilePath, M1.FileOffset, LHS.DiagnosticName,
733 std::tie(M2.FilePath, M2.FileOffset, RHS.DiagnosticName, M2.Message);
736struct EqualClangTidyError {
738 LessClangTidyError Less;
739 return !Less(LHS, RHS) && !Less(RHS, LHS);
747 llvm::stable_sort(Errors, LessClangTidyError());
748 Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
750 if (RemoveIncompatibleErrors)
751 removeIncompatibleErrors();
752 return std::move(Errors);
756struct LessClangTidyErrorWithoutDiagnosticName {
758 const tooling::DiagnosticMessage &M1 = LHS->Message;
759 const tooling::DiagnosticMessage &M2 = RHS->Message;
761 return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
762 std::tie(M2.FilePath, M2.FileOffset, M2.Message);
767void ClangTidyDiagnosticConsumer::removeDuplicatedDiagnosticsOfAliasCheckers() {
768 using UniqueErrorSet =
769 std::set<ClangTidyError *, LessClangTidyErrorWithoutDiagnosticName>;
770 UniqueErrorSet UniqueErrors;
772 auto IT = Errors.begin();
773 while (IT != Errors.end()) {
775 std::pair<UniqueErrorSet::iterator, bool> Inserted =
776 UniqueErrors.insert(&
Error);
779 if (Inserted.second) {
783 const llvm::StringMap<tooling::Replacements> &CandidateFix =
785 const llvm::StringMap<tooling::Replacements> &ExistingFix =
786 (*Inserted.first)->
Message.Fix;
788 if (CandidateFix != ExistingFix) {
791 ExistingError.Message.Fix.clear();
792 ExistingError.Notes.emplace_back(
793 llvm::formatv(
"cannot apply fix-it because an alias checker has "
794 "suggested a different fix-it; please remove one of "
795 "the checkers ('{0}', '{1}') or "
796 "ensure they are both configured the same",
797 ExistingError.DiagnosticName,
Error.DiagnosticName)
801 if (
Error.IsWarningAsError)
806 IT = Errors.erase(IT);
static bool parseFileExtensions(llvm::ArrayRef< std::string > AllFileExtensions, FileExtensionsSet &FileExtensions)
static cl::opt< bool > Fix("fix", desc(R"(
Apply suggested fixes. Without -fix-errors
clang-tidy will bail out if any compilation
errors were found.
)"), cl::init(false), cl::cat(ClangTidyCategory))
static cl::opt< bool > AllowEnablingAnalyzerAlphaCheckers("allow-enabling-analyzer-alpha-checkers", cl::init(false), cl::Hidden, cl::cat(ClangTidyCategory))
This option allows enabling the experimental alpha checkers from the static analyzer.
static cl::opt< bool > EnableModuleHeadersParsing("enable-module-headers-parsing", desc(R"(
Enables preprocessor-level module header parsing
for C++20 and above, empowering specific checks
to detect macro definitions within modules. This
feature may cause performance and parsing issues
and is therefore considered experimental.
)"), cl::init(false), cl::cat(ClangTidyCategory))
CodeCompletionBuilder Builder
static constexpr llvm::SourceMgr::DiagKind Error
DiagnosticCallback Diagnostic
std::vector< llvm::unique_function< void(const Params &, Config &) const > > Apply
CharSourceRange Range
SourceRange for the file name.
std::vector< FixItHint > Hints
std::optional< FixItHint > FixIt
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
bool isCheckEnabled(StringRef CheckName) const
Returns true if the check is enabled for the CurrentFile.
std::string getCheckName(unsigned DiagnosticID) const
Returns the name of the clang-tidy check which produced this diagnostic ID.
const ClangTidyOptions & getOptions() const
Returns options for CurrentFile.
const std::string & getCurrentBuildDirectory() const
Returns build directory of the current translation unit.
const LangOptions & getLangOpts() const
Gets the language options from the AST context.
DiagnosticBuilder configurationDiag(StringRef Message, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors to do with reading the configuration using this method.
void setASTContext(ASTContext *Context)
Sets ASTContext for the current translation unit.
void setProfileStoragePrefix(StringRef ProfilePrefix)
Control storage of profile date.
ClangTidyContext(std::unique_ptr< ClangTidyOptionsProvider > OptionsProvider, bool AllowEnablingAnalyzerAlphaCheckers=false, bool EnableModuleHeadersParsing=false)
Initializes ClangTidyContext instance.
void setEnableProfiling(bool Profile)
Control profile collection in clang-tidy.
DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, SourceLocation Loc)
void setCurrentFile(StringRef File)
Should be called when starting to process new translation unit.
bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, SmallVectorImpl< tooling::Diagnostic > &NoLintErrors, bool AllowIO=true, bool EnableNoLintBlocks=true)
Check whether a given diagnostic should be suppressed due to the presence of a "NOLINT" suppression c...
bool treatAsError(StringRef CheckName) const
Returns true if the check should be upgraded to error for the CurrentFile.
DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors detected using this method.
ClangTidyOptions getOptionsForFile(StringRef File) const
Returns options for File.
std::optional< ClangTidyProfiling::StorageParams > getProfileStorageParams() const
const ClangTidyGlobalOptions & getGlobalOptions() const
Returns global options.
void setSourceManager(SourceManager *SourceMgr)
Sets the SourceManager of the used DiagnosticsEngine.
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx, DiagnosticsEngine *ExternalDiagEngine=nullptr, bool RemoveIncompatibleErrors=true, bool GetFixesFromNotes=false, bool EnableNolintBlocks=true)
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
std::vector< ClangTidyError > take()
bool shouldSuppress(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Diag, llvm::StringRef DiagName, llvm::SmallVectorImpl< tooling::Diagnostic > &NoLintErrors, bool AllowIO, bool EnableNoLintBlocks)
bool operator<(const Ref &L, const Ref &R)
constexpr llvm::StringLiteral Message
const llvm::StringMap< tooling::Replacements > * getFixIt(const tooling::Diagnostic &Diagnostic, bool AnyFix)
Gets the Fix attached to Diagnostic.
llvm::SmallSet< llvm::StringRef, 5 > FileExtensionsSet
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A detected error complete with information to display diagnostic and automatic fix.
ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory, bool IsWarningAsError)
std::vector< std::string > EnabledDiagnosticAliases
std::vector< FileFilter > LineFilter
Output warnings from certain line ranges of certain files only.
Contains options for clang-tidy.
ClangTidyOptions merge(const ClangTidyOptions &Other, unsigned Order) const
Creates a new ClangTidyOptions instance combined from all fields of this instance overridden by the f...
std::optional< std::string > HeaderFilterRegex
Output warnings from headers matching this filter.
std::optional< bool > SystemHeaders
Output warnings from system headers matching HeaderFilterRegex.
static ClangTidyOptions getDefaults()
These options are used for all settings that haven't been overridden by the OptionsProvider.
unsigned ErrorsIgnoredCheckFilter
unsigned ErrorsIgnoredNonUserCode
unsigned ErrorsIgnoredLineFilter
unsigned ErrorsIgnoredNOLINT
Contains a list of line ranges in a single file.
std::pair< unsigned int, unsigned int > LineRange
LineRange is a pair<start, end> (inclusive).