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,
142 void emitBuildingModuleLocation(FullSourceLoc
Loc, PresumedLoc PLoc,
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) {
323 ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
327void ClangTidyDiagnosticConsumer::finalizeLastError() {
328 if (!Errors.empty()) {
330 if (
Error.DiagnosticName ==
"clang-tidy-config") {
333 Error.DiagLevel != ClangTidyError::Error) {
336 }
else if (!LastErrorRelatesToUserCode) {
339 }
else if (!LastErrorPassesLineFilter) {
346 LastErrorRelatesToUserCode =
false;
347 LastErrorPassesLineFilter =
false;
352const llvm::StringMap<tooling::Replacements> *
358 const llvm::StringMap<tooling::Replacements> *Result =
nullptr;
360 if (!Note.Fix.empty()) {
374 if (LastErrorWasIgnored && DiagLevel == DiagnosticsEngine::Note)
377 SmallVector<tooling::Diagnostic, 1> SuppressionErrors;
379 EnableNolintBlocks)) {
382 LastErrorWasIgnored =
true;
383 Context.DiagEngine->Clear();
384 for (
const auto &
Error : SuppressionErrors)
389 LastErrorWasIgnored =
false;
391 DiagnosticConsumer::HandleDiagnostic(DiagLevel,
Info);
393 if (DiagLevel == DiagnosticsEngine::Note) {
394 assert(!Errors.empty() &&
395 "A diagnostic note can only be appended to a message.");
399 if (CheckName.empty()) {
403 case DiagnosticsEngine::Error:
404 case DiagnosticsEngine::Fatal:
405 CheckName =
"clang-diagnostic-error";
407 case DiagnosticsEngine::Warning:
408 CheckName =
"clang-diagnostic-warning";
410 case DiagnosticsEngine::Remark:
411 CheckName =
"clang-diagnostic-remark";
414 CheckName =
"clang-diagnostic-unknown";
419 ClangTidyError::Level Level = ClangTidyError::Warning;
420 if (DiagLevel == DiagnosticsEngine::Error ||
421 DiagLevel == DiagnosticsEngine::Fatal) {
424 Level = ClangTidyError::Error;
425 LastErrorRelatesToUserCode =
true;
426 LastErrorPassesLineFilter =
true;
427 }
else if (DiagLevel == DiagnosticsEngine::Remark) {
428 Level = ClangTidyError::Remark;
431 bool IsWarningAsError = DiagLevel == DiagnosticsEngine::Warning &&
437 if (ExternalDiagEngine) {
440 forwardDiagnostic(
Info);
442 ClangTidyDiagnosticRenderer Converter(
443 Context.
getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),
445 SmallString<100> Message;
446 Info.FormatDiagnostic(Message);
448 if (
Info.hasSourceManager())
449 Loc = FullSourceLoc(
Info.getLocation(),
Info.getSourceManager());
450 else if (Context.DiagEngine->hasSourceManager())
451 Loc = FullSourceLoc(
Info.getLocation(),
452 Context.DiagEngine->getSourceManager());
453 Converter.emitDiagnostic(
Loc, DiagLevel, Message,
Info.getRanges(),
454 Info.getFixItHints());
457 if (
Info.hasSourceManager())
458 checkFilters(
Info.getLocation(),
Info.getSourceManager());
460 Context.DiagEngine->Clear();
461 for (
const auto &
Error : SuppressionErrors)
465bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef
FileName,
466 unsigned LineNumber)
const {
470 if (
FileName.ends_with(Filter.Name)) {
471 if (Filter.LineRanges.empty())
474 if (
Range.first <= LineNumber && LineNumber <=
Range.second)
483void ClangTidyDiagnosticConsumer::forwardDiagnostic(
const Diagnostic &
Info) {
485 auto DiagLevelAndFormatString =
487 unsigned ExternalID = ExternalDiagEngine->getDiagnosticIDs()->getCustomDiagID(
488 DiagLevelAndFormatString.first, DiagLevelAndFormatString.second);
491 auto Builder = ExternalDiagEngine->Report(
Info.getLocation(), ExternalID);
492 for (
const FixItHint &Hint :
Info.getFixItHints())
494 for (
auto Range :
Info.getRanges())
496 for (
unsigned Index = 0; Index <
Info.getNumArgs(); ++Index) {
497 DiagnosticsEngine::ArgumentKind
Kind =
Info.getArgKind(Index);
499 case clang::DiagnosticsEngine::ak_std_string:
502 case clang::DiagnosticsEngine::ak_c_string:
505 case clang::DiagnosticsEngine::ak_sint:
508 case clang::DiagnosticsEngine::ak_uint:
511 case clang::DiagnosticsEngine::ak_tokenkind:
512 Builder << static_cast<tok::TokenKind>(
Info.getRawArg(Index));
514 case clang::DiagnosticsEngine::ak_identifierinfo:
517 case clang::DiagnosticsEngine::ak_qual:
518 Builder << Qualifiers::fromOpaqueValue(
Info.getRawArg(Index));
520 case clang::DiagnosticsEngine::ak_qualtype:
521 Builder << QualType::getFromOpaquePtr((
void *)
Info.getRawArg(Index));
523 case clang::DiagnosticsEngine::ak_declarationname:
524 Builder << DeclarationName::getFromOpaqueInteger(
Info.getRawArg(Index));
526 case clang::DiagnosticsEngine::ak_nameddecl:
527 Builder << reinterpret_cast<const NamedDecl *>(
Info.getRawArg(Index));
529 case clang::DiagnosticsEngine::ak_nestednamespec:
530 Builder << reinterpret_cast<NestedNameSpecifier *>(
Info.getRawArg(Index));
532 case clang::DiagnosticsEngine::ak_declcontext:
533 Builder << reinterpret_cast<DeclContext *>(
Info.getRawArg(Index));
535 case clang::DiagnosticsEngine::ak_qualtype_pair:
538 case clang::DiagnosticsEngine::ak_attr:
539 Builder << reinterpret_cast<Attr *>(
Info.getRawArg(Index));
541 case clang::DiagnosticsEngine::ak_addrspace:
542 Builder << static_cast<LangAS>(
Info.getRawArg(Index));
548void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation
Location,
549 const SourceManager &Sources) {
552 LastErrorRelatesToUserCode =
true;
553 LastErrorPassesLineFilter =
true;
564 FileID FID = Sources.getDecomposedExpansionLoc(
Location).first;
565 OptionalFileEntryRef File = Sources.getFileEntryRefForID(FID);
570 LastErrorRelatesToUserCode =
true;
571 LastErrorPassesLineFilter =
true;
575 StringRef
FileName(File->getName());
576 LastErrorRelatesToUserCode =
577 LastErrorRelatesToUserCode || Sources.isInMainFile(
Location) ||
580 !(ExcludeHeaderFilter && ExcludeHeaderFilter->match(
FileName))));
582 unsigned LineNumber = Sources.getExpansionLineNumber(
Location);
583 LastErrorPassesLineFilter =
584 LastErrorPassesLineFilter || passesLineFilter(
FileName, LineNumber);
587void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
604 Event(
unsigned Begin,
unsigned End, EventType
Type,
unsigned ErrorId,
634 Priority = std::make_tuple(Begin,
Type, -End, -ErrorSize, ErrorId);
637 Priority = std::make_tuple(Begin,
Type, -End, ErrorSize, ErrorId);
640 Priority = std::make_tuple(End,
Type, -Begin, ErrorSize, ErrorId);
645 bool operator<(
const Event &Other)
const {
646 return Priority < Other.Priority;
655 std::tuple<unsigned, EventType, int, int, unsigned> Priority;
658 removeDuplicatedDiagnosticsOfAliasCheckers();
661 std::vector<int> Sizes;
663 std::pair<ClangTidyError *, llvm::StringMap<tooling::Replacements> *>>
665 for (
auto &
Error : Errors) {
667 ErrorFixes.emplace_back(
668 &
Error,
const_cast<llvm::StringMap<tooling::Replacements> *
>(
Fix));
670 for (
const auto &ErrorAndFix : ErrorFixes) {
672 for (
const auto &FileAndReplaces : *ErrorAndFix.second) {
673 for (
const auto &Replace : FileAndReplaces.second)
674 Size += Replace.getLength();
676 Sizes.push_back(Size);
680 llvm::StringMap<std::vector<Event>> FileEvents;
681 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
682 for (
const auto &FileAndReplace : *ErrorFixes[I].second) {
683 for (
const auto &Replace : FileAndReplace.second) {
684 unsigned Begin = Replace.getOffset();
685 unsigned End = Begin + Replace.getLength();
686 auto &Events = FileEvents[Replace.getFilePath()];
688 Events.emplace_back(Begin, End, Event::ET_Insert, I, Sizes[I]);
690 Events.emplace_back(Begin, End, Event::ET_Begin, I, Sizes[I]);
691 Events.emplace_back(Begin, End, Event::ET_End, I, Sizes[I]);
697 llvm::BitVector
Apply(ErrorFixes.size(),
true);
698 for (
auto &FileAndEvents : FileEvents) {
699 std::vector<Event> &Events = FileAndEvents.second;
702 int OpenIntervals = 0;
703 for (
const auto &Event : Events) {
704 switch (
Event.Type) {
705 case Event::ET_Begin:
706 if (OpenIntervals++ != 0)
709 case Event::ET_Insert:
710 if (OpenIntervals != 0)
714 if (--OpenIntervals != 0)
719 assert(OpenIntervals == 0 &&
"Amount of begin/end points doesn't match");
722 for (
unsigned I = 0; I < ErrorFixes.size(); ++I) {
724 ErrorFixes[I].second->clear();
725 ErrorFixes[I].first->Notes.emplace_back(
726 "this fix will not be applied because it overlaps with another fix");
732struct LessClangTidyError {
734 const tooling::DiagnosticMessage &M1 = LHS.Message;
735 const tooling::DiagnosticMessage &M2 = RHS.Message;
737 return std::tie(M1.FilePath, M1.FileOffset, LHS.DiagnosticName,
739 std::tie(M2.FilePath, M2.FileOffset, RHS.DiagnosticName, M2.Message);
742struct EqualClangTidyError {
744 LessClangTidyError Less;
745 return !Less(LHS, RHS) && !Less(RHS, LHS);
753 llvm::stable_sort(Errors, LessClangTidyError());
754 Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()),
756 if (RemoveIncompatibleErrors)
757 removeIncompatibleErrors();
758 return std::move(Errors);
762struct LessClangTidyErrorWithoutDiagnosticName {
764 const tooling::DiagnosticMessage &M1 = LHS->Message;
765 const tooling::DiagnosticMessage &M2 = RHS->Message;
767 return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
768 std::tie(M2.FilePath, M2.FileOffset, M2.Message);
773void ClangTidyDiagnosticConsumer::removeDuplicatedDiagnosticsOfAliasCheckers() {
774 using UniqueErrorSet =
775 std::set<ClangTidyError *, LessClangTidyErrorWithoutDiagnosticName>;
776 UniqueErrorSet UniqueErrors;
778 auto IT = Errors.begin();
779 while (IT != Errors.end()) {
781 std::pair<UniqueErrorSet::iterator, bool> Inserted =
782 UniqueErrors.insert(&
Error);
785 if (Inserted.second) {
789 const llvm::StringMap<tooling::Replacements> &CandidateFix =
791 const llvm::StringMap<tooling::Replacements> &ExistingFix =
792 (*Inserted.first)->
Message.Fix;
794 if (CandidateFix != ExistingFix) {
797 ExistingError.Message.Fix.clear();
798 ExistingError.Notes.emplace_back(
799 llvm::formatv(
"cannot apply fix-it because an alias checker has "
800 "suggested a different fix-it; please remove one of "
801 "the checkers ('{0}', '{1}') or "
802 "ensure they are both configured the same",
803 ExistingError.DiagnosticName,
Error.DiagnosticName)
807 if (
Error.IsWarningAsError)
812 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.
std::optional< std::string > ExcludeHeaderFilterRegex
Exclude warnings from headers matching this filter, even if they match HeaderFilterRegex.
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).