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 if (
Message.endswith(CheckNameInMessage))
70 ? tooling::DiagnosticMessage(Message,
Loc.getManager(),
Loc)
71 : tooling::DiagnosticMessage(
Message);
77 auto ToCharRange = [
this, &
Loc](
const CharSourceRange &SourceRange) {
78 if (SourceRange.isCharRange())
80 assert(SourceRange.isTokenRange());
81 SourceLocation End = Lexer::getLocForEndOfToken(
82 SourceRange.getEnd(), 0,
Loc.getManager(), LangOpts);
83 return CharSourceRange::getCharRange(SourceRange.getBegin(), End);
88 llvm::make_filter_range(Ranges, [](
const CharSourceRange &R) {
89 return R.getAsRange().isValid();
92 if (Level == DiagnosticsEngine::Note) {
93 Error.Notes.push_back(TidyMessage);
94 for (
const CharSourceRange &SourceRange : ValidRanges)
95 Error.Notes.back().Ranges.emplace_back(
Loc.getManager(),
96 ToCharRange(SourceRange));
99 assert(
Error.Message.Message.empty() &&
"Overwriting a diagnostic message");
100 Error.Message = TidyMessage;
101 for (
const CharSourceRange &SourceRange : ValidRanges)
102 Error.Message.Ranges.emplace_back(
Loc.getManager(),
103 ToCharRange(SourceRange));
106 void emitDiagnosticLoc(FullSourceLoc
Loc, PresumedLoc PLoc,
107 DiagnosticsEngine::Level Level,
108 ArrayRef<CharSourceRange> Ranges)
override {}
110 void emitCodeContext(FullSourceLoc
Loc, DiagnosticsEngine::Level Level,
111 SmallVectorImpl<CharSourceRange> &Ranges,
112 ArrayRef<FixItHint>
Hints)
override {
113 assert(
Loc.isValid());
114 tooling::DiagnosticMessage *DiagWithFix =
115 Level == DiagnosticsEngine::Note ? &
Error.Notes.back() : &
Error.Message;
119 assert(
Range.getBegin().isValid() &&
Range.getEnd().isValid() &&
120 "Invalid range in the fix-it hint.");
121 assert(
Range.getBegin().isFileID() &&
Range.getEnd().isFileID() &&
122 "Only file locations supported in fix-it hints.");
124 tooling::Replacement Replacement(
Loc.getManager(), Range,
127 DiagWithFix->Fix[Replacement.getFilePath()].add(Replacement);
131 llvm::errs() <<
"Fix conflicts with existing fix! "
132 << llvm::toString(std::move(Err)) <<
"\n";
133 assert(
false &&
"Fix conflicts with existing fix!");
138 void emitIncludeLocation(FullSourceLoc
Loc, PresumedLoc PLoc)
override {}
140 void emitImportLocation(FullSourceLoc
Loc, PresumedLoc PLoc,
141 StringRef ModuleName)
override {}
143 void emitBuildingModuleLocation(FullSourceLoc
Loc, PresumedLoc PLoc,
144 StringRef ModuleName)
override {}
146 void endDiagnostic(DiagOrStoredDiag D,
147 DiagnosticsEngine::Level Level)
override {
148 assert(!
Error.Message.Message.empty() &&
"Message has not been set");
157 ClangTidyError::Level DiagLevel,
158 StringRef BuildDirectory,
bool IsWarningAsError)
159 : tooling::
Diagnostic(CheckName, DiagLevel, BuildDirectory),
160 IsWarningAsError(IsWarningAsError) {}
163 std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
165 : OptionsProvider(std::move(OptionsProvider)),
177 StringRef CheckName, SourceLocation
Loc, StringRef Description,
178 DiagnosticIDs::Level Level ) {
179 assert(
Loc.isValid());
180 unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
181 Level, (Description +
" [" + CheckName +
"]").str());
182 CheckNamesByDiagnosticID.try_emplace(
ID, CheckName);
183 return DiagEngine->Report(
Loc,
ID);
187 StringRef CheckName, StringRef Description,
188 DiagnosticIDs::Level Level ) {
189 unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
190 Level, (Description +
" [" + CheckName +
"]").str());
191 CheckNamesByDiagnosticID.try_emplace(
ID, CheckName);
192 return DiagEngine->Report(
ID);
196 SourceManager &SM = DiagEngine->getSourceManager();
197 FileManager &FM = SM.getFileManager();
198 FileEntryRef File = llvm::cantFail(FM.getFileRef(
Error.Message.FilePath));
199 FileID
ID = SM.getOrCreateFileID(File, SrcMgr::C_User);
200 SourceLocation FileStartLoc = SM.getLocForStartOfFile(
ID);
201 SourceLocation
Loc = FileStartLoc.getLocWithOffset(
202 static_cast<SourceLocation::IntTy
>(
Error.Message.FileOffset));
204 static_cast<DiagnosticIDs::Level
>(
Error.DiagLevel));
209 DiagnosticIDs::Level Level ) {
210 return diag(
"clang-tidy-config", Message, Level);
215 SmallVectorImpl<tooling::Diagnostic> &NoLintErrors,
bool AllowIO,
216 bool EnableNoLintBlocks) {
219 AllowIO, EnableNoLintBlocks);
223 DiagEngine->setSourceManager(SourceMgr);
228 FileExtensions.clear();
229 for (StringRef
Suffix : AllFileExtensions) {
230 StringRef Extension =
Suffix.trim();
231 if (!llvm::all_of(Extension, isAlphanumeric))
233 FileExtensions.insert(Extension);
239 CurrentFile = std::string(File);
241 CheckFilter = std::make_unique<CachedGlobList>(*
getOptions().Checks);
242 WarningAsErrorFilter =
243 std::make_unique<CachedGlobList>(*
getOptions().WarningsAsErrors);
245 HeaderFileExtensions))
248 ImplementationFileExtensions))
253 DiagEngine->SetArgToStringFn(&FormatASTNodeDiagnosticArgument, Context);
254 LangOpts = Context->getLangOpts();
258 return OptionsProvider->getGlobalOptions();
262 return CurrentOptions;
269 OptionsProvider->getOptions(File), 0);
275 ProfilePrefix = std::string(Prefix);
278std::optional<ClangTidyProfiling::StorageParams>
280 if (ProfilePrefix.empty())
287 assert(CheckFilter !=
nullptr);
288 return CheckFilter->contains(CheckName);
292 assert(WarningAsErrorFilter !=
nullptr);
293 return WarningAsErrorFilter->contains(CheckName);
297 std::string ClangWarningOption = std::string(
298 DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(DiagnosticID));
299 if (!ClangWarningOption.empty())
300 return "clang-diagnostic-" + ClangWarningOption;
301 llvm::DenseMap<unsigned, std::string>::const_iterator I =
302 CheckNamesByDiagnosticID.find(DiagnosticID);
303 if (I != CheckNamesByDiagnosticID.end())
310 bool RemoveIncompatibleErrors,
bool GetFixesFromNotes,
311 bool EnableNolintBlocks)
312 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
313 RemoveIncompatibleErrors(RemoveIncompatibleErrors),
314 GetFixesFromNotes(GetFixesFromNotes),
315 EnableNolintBlocks(EnableNolintBlocks) {}
317void ClangTidyDiagnosticConsumer::finalizeLastError() {
318 if (!Errors.empty()) {
320 if (
Error.DiagnosticName ==
"clang-tidy-config") {
323 Error.DiagLevel != ClangTidyError::Error) {
326 }
else if (!LastErrorRelatesToUserCode) {
329 }
else if (!LastErrorPassesLineFilter) {
336 LastErrorRelatesToUserCode =
false;
337 LastErrorPassesLineFilter =
false;
342const llvm::StringMap<tooling::Replacements> *
348 const llvm::StringMap<tooling::Replacements> *Result =
nullptr;
350 if (!Note.Fix.empty()) {
364 if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
367 SmallVector<tooling::Diagnostic, 1> SuppressionErrors;
369 EnableNolintBlocks)) {
372 LastErrorWasIgnored =
true;
373 Context.DiagEngine->Clear();
374 for (
const auto &
Error : SuppressionErrors)
379 LastErrorWasIgnored =
false;
381 DiagnosticConsumer::HandleDiagnostic(DiagLevel,
Info);
383 if (DiagLevel == DiagnosticsEngine::Note) {
384 assert(!Errors.empty() &&
385 "A diagnostic note can only be appended to a message.");
389 if (CheckName.empty()) {
393 case DiagnosticsEngine::Error:
394 case DiagnosticsEngine::Fatal:
395 CheckName =
"clang-diagnostic-error";
397 case DiagnosticsEngine::Warning:
398 CheckName =
"clang-diagnostic-warning";
400 case DiagnosticsEngine::Remark:
401 CheckName =
"clang-diagnostic-remark";
404 CheckName =
"clang-diagnostic-unknown";
409 ClangTidyError::Level Level = ClangTidyError::Warning;
410 if (DiagLevel == DiagnosticsEngine::Error ||
411 DiagLevel == DiagnosticsEngine::Fatal) {
414 Level = ClangTidyError::Error;
415 LastErrorRelatesToUserCode =
true;
416 LastErrorPassesLineFilter =
true;
417 }
else if (DiagLevel == DiagnosticsEngine::Remark) {
418 Level = ClangTidyError::Remark;
421 bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning &&
427 if (ExternalDiagEngine) {
430 forwardDiagnostic(
Info);
432 ClangTidyDiagnosticRenderer Converter(
433 Context.
getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),
435 SmallString<100> Message;
436 Info.FormatDiagnostic(Message);
438 if (
Info.hasSourceManager())
439 Loc = FullSourceLoc(
Info.getLocation(),
Info.getSourceManager());
440 else if (Context.DiagEngine->hasSourceManager())
441 Loc = FullSourceLoc(
Info.getLocation(),
442 Context.DiagEngine->getSourceManager());
443 Converter.emitDiagnostic(
Loc, DiagLevel, Message,
Info.getRanges(),
444 Info.getFixItHints());
447 if (
Info.hasSourceManager())
448 checkFilters(
Info.getLocation(),
Info.getSourceManager());
450 Context.DiagEngine->Clear();
451 for (
const auto &
Error : SuppressionErrors)
455bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef
FileName,
456 unsigned LineNumber)
const {
460 if (
FileName.endswith(Filter.Name)) {
461 if (Filter.LineRanges.empty())
464 if (
Range.first <= LineNumber && LineNumber <=
Range.second)
473void ClangTidyDiagnosticConsumer::forwardDiagnostic(
const Diagnostic &
Info) {
475 auto DiagLevelAndFormatString =
477 unsigned ExternalID = ExternalDiagEngine->getDiagnosticIDs()->getCustomDiagID(
478 DiagLevelAndFormatString.first, DiagLevelAndFormatString.second);
481 auto Builder = ExternalDiagEngine->Report(
Info.getLocation(), ExternalID);
482 for (
const FixItHint &Hint :
Info.getFixItHints())
484 for (
auto Range :
Info.getRanges())
486 for (
unsigned Index = 0; Index <
Info.getNumArgs(); ++Index) {
487 DiagnosticsEngine::ArgumentKind
Kind =
Info.getArgKind(Index);
489 case clang::DiagnosticsEngine::ak_std_string:
492 case clang::DiagnosticsEngine::ak_c_string:
495 case clang::DiagnosticsEngine::ak_sint:
498 case clang::DiagnosticsEngine::ak_uint:
501 case clang::DiagnosticsEngine::ak_tokenkind:
502 Builder << static_cast<tok::TokenKind>(
Info.getRawArg(Index));
504 case clang::DiagnosticsEngine::ak_identifierinfo:
507 case clang::DiagnosticsEngine::ak_qual:
508 Builder << Qualifiers::fromOpaqueValue(
Info.getRawArg(Index));
510 case clang::DiagnosticsEngine::ak_qualtype:
511 Builder << QualType::getFromOpaquePtr((
void *)
Info.getRawArg(Index));
513 case clang::DiagnosticsEngine::ak_declarationname:
514 Builder << DeclarationName::getFromOpaqueInteger(
Info.getRawArg(Index));
516 case clang::DiagnosticsEngine::ak_nameddecl:
517 Builder << reinterpret_cast<const NamedDecl *>(
Info.getRawArg(Index));
519 case clang::DiagnosticsEngine::ak_nestednamespec:
520 Builder << reinterpret_cast<NestedNameSpecifier *>(
Info.getRawArg(Index));
522 case clang::DiagnosticsEngine::ak_declcontext:
523 Builder << reinterpret_cast<DeclContext *>(
Info.getRawArg(Index));
525 case clang::DiagnosticsEngine::ak_qualtype_pair:
528 case clang::DiagnosticsEngine::ak_attr:
529 Builder << reinterpret_cast<Attr *>(
Info.getRawArg(Index));
531 case clang::DiagnosticsEngine::ak_addrspace:
532 Builder << static_cast<LangAS>(
Info.getRawArg(Index));
538void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation
Location,
539 const SourceManager &Sources) {
542 LastErrorRelatesToUserCode =
true;
543 LastErrorPassesLineFilter =
true;
554 FileID FID = Sources.getDecomposedExpansionLoc(
Location).first;
555 OptionalFileEntryRef File = Sources.getFileEntryRefForID(FID);
560 LastErrorRelatesToUserCode =
true;
561 LastErrorPassesLineFilter =
true;
565 StringRef
FileName(File->getName());
566 LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
570 unsigned LineNumber = Sources.getExpansionLineNumber(
Location);
571 LastErrorPassesLineFilter =
572 LastErrorPassesLineFilter || passesLineFilter(
FileName, LineNumber);
575llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
579 return HeaderFilter.get();
582void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
599 Event(
unsigned Begin,
unsigned End, EventType
Type,
unsigned ErrorId,
629 Priority = std::make_tuple(Begin,
Type, -End, -ErrorSize, ErrorId);
632 Priority = std::make_tuple(Begin,
Type, -End, ErrorSize, ErrorId);
635 Priority = std::make_tuple(End,
Type, -Begin, ErrorSize, ErrorId);
640 bool operator<(
const Event &Other)
const {
641 return Priority < Other.Priority;
650 std::tuple<unsigned, EventType, int, int, unsigned> Priority;
653 removeDuplicatedDiagnosticsOfAliasCheckers();
656 std::vector<int> Sizes;
658 std::pair<ClangTidyError *, llvm::StringMap<tooling::Replacements> *>>
660 for (
auto &
Error : Errors) {
662 ErrorFixes.emplace_back(
663 &
Error,
const_cast<llvm::StringMap<tooling::Replacements> *
>(
Fix));
665 for (
const auto &ErrorAndFix : ErrorFixes) {
667 for (
const auto &FileAndReplaces : *ErrorAndFix.second) {
668 for (
const auto &Replace : FileAndReplaces.second)
669 Size += Replace.getLength();
671 Sizes.push_back(Size);
675 llvm::StringMap<std::vector<Event>> FileEvents;
676 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
677 for (
const auto &FileAndReplace : *ErrorFixes[I].second) {
678 for (
const auto &Replace : FileAndReplace.second) {
679 unsigned Begin = Replace.getOffset();
680 unsigned End = Begin + Replace.getLength();
681 auto &Events = FileEvents[Replace.getFilePath()];
683 Events.emplace_back(Begin, End, Event::ET_Insert, I, Sizes[I]);
685 Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);
686 Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);
692 llvm::BitVector
Apply(ErrorFixes.size(),
true);
693 for (
auto &FileAndEvents : FileEvents) {
694 std::vector<Event> &Events = FileAndEvents.second;
697 int OpenIntervals = 0;
698 for (
const auto &Event : Events) {
699 switch (
Event.Type) {
700 case Event::ET_Begin:
701 if (OpenIntervals++ != 0)
704 case Event::ET_Insert:
705 if (OpenIntervals != 0)
709 if (--OpenIntervals != 0)
714 assert(OpenIntervals == 0 &&
"Amount of begin/end points doesn't match");
717 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
719 ErrorFixes[I].second->clear();
720 ErrorFixes[I].first->Notes.emplace_back(
721 "this fix will not be applied because it overlaps with another fix");
727struct LessClangTidyError {
729 const tooling::DiagnosticMessage &M1 = LHS.Message;
730 const tooling::DiagnosticMessage &M2 = RHS.Message;
732 return std::tie(M1.FilePath, M1.FileOffset, LHS.DiagnosticName,
734 std::tie(M2.FilePath, M2.FileOffset, RHS.DiagnosticName, M2.Message);
737struct EqualClangTidyError {
739 LessClangTidyError Less;
740 return !Less(LHS, RHS) && !Less(RHS, LHS);
748 llvm::stable_sort(Errors, LessClangTidyError());
749 Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
751 if (RemoveIncompatibleErrors)
752 removeIncompatibleErrors();
753 return std::move(Errors);
757struct LessClangTidyErrorWithoutDiagnosticName {
759 const tooling::DiagnosticMessage &M1 = LHS->Message;
760 const tooling::DiagnosticMessage &M2 = RHS->Message;
762 return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
763 std::tie(M2.FilePath, M2.FileOffset, M2.Message);
768void ClangTidyDiagnosticConsumer::removeDuplicatedDiagnosticsOfAliasCheckers() {
769 using UniqueErrorSet =
770 std::set<ClangTidyError *, LessClangTidyErrorWithoutDiagnosticName>;
771 UniqueErrorSet UniqueErrors;
773 auto IT = Errors.begin();
774 while (IT != Errors.end()) {
776 std::pair<UniqueErrorSet::iterator, bool> Inserted =
777 UniqueErrors.insert(&
Error);
780 if (Inserted.second) {
784 const llvm::StringMap<tooling::Replacements> &CandidateFix =
786 const llvm::StringMap<tooling::Replacements> &ExistingFix =
787 (*Inserted.first)->
Message.Fix;
789 if (CandidateFix != ExistingFix) {
792 ExistingError.Message.Fix.clear();
793 ExistingError.Notes.emplace_back(
794 llvm::formatv(
"cannot apply fix-it because an alias checker has "
795 "suggested a different fix-it; please remove one of "
796 "the checkers ('{0}', '{1}') or "
797 "ensure they are both configured the same",
798 ExistingError.DiagnosticName,
Error.DiagnosticName)
802 if (
Error.IsWarningAsError)
807 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).