9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
14#include "clang/ASTMatchers/ASTMatchFinder.h"
15#include "clang/Basic/Diagnostic.h"
31 static ArrayRef<std::pair<T, StringRef>>
getEnumMapping() =
delete;
53class ClangTidyCheck :
public ast_matchers::MatchFinder::MatchCallback {
68 virtual bool isLanguageVersionSupported(
const LangOptions &LangOpts)
const {
90 virtual void registerPPCallbacks(
const SourceManager &SM, Preprocessor *PP,
91 Preprocessor *ModuleExpanderPP) {}
108 virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {}
112 virtual void check(
const ast_matchers::MatchFinder::MatchResult &Result) {}
115 DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
116 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
119 DiagnosticBuilder diag(StringRef Description,
120 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
124 configurationDiag(StringRef Description,
125 DiagnosticIDs::Level Level = DiagnosticIDs::Warning)
const;
140 void diagnoseBadIntegerOption(
const Twine &Lookup,
141 StringRef Unparsed)
const;
142 void diagnoseBadBooleanOption(
const Twine &Lookup,
143 StringRef Unparsed)
const;
144 void diagnoseBadEnumOption(
const Twine &Lookup, StringRef Unparsed,
145 StringRef Suggestion = StringRef())
const;
149 OptionsView(StringRef CheckName,
151 ClangTidyContext *Context);
158 std::optional<StringRef> get(StringRef LocalName)
const;
165 StringRef get(StringRef LocalName, StringRef Default)
const;
173 std::optional<StringRef> getLocalOrGlobal(StringRef LocalName)
const;
181 StringRef getLocalOrGlobal(StringRef LocalName, StringRef Default)
const;
192 template <
typename T>
193 std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
194 get(StringRef LocalName)
const {
195 if (std::optional<StringRef> Value = get(LocalName)) {
197 if (!StringRef(*Value).getAsInteger(10, Result))
199 diagnoseBadIntegerOption(NamePrefix + LocalName, *Value);
214 template <
typename T>
215 std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
216 get(StringRef LocalName, std::optional<T> Default)
const {
217 if (std::optional<StringRef> Value = get(LocalName)) {
218 if (Value ==
"" || Value ==
"none" || Value ==
"null" ||
219 (std::is_unsigned_v<T> && Value ==
"-1"))
222 if (!StringRef(*Value).getAsInteger(10, Result))
224 diagnoseBadIntegerOption(NamePrefix + LocalName, *Value);
238 template <
typename T>
239 std::enable_if_t<std::is_integral_v<T>,
T> get(StringRef LocalName,
241 return get<T>(LocalName).value_or(Default);
254 template <
typename T>
255 std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
256 getLocalOrGlobal(StringRef LocalName)
const {
257 std::optional<StringRef> ValueOr = get(LocalName);
258 bool IsGlobal =
false;
261 ValueOr = getLocalOrGlobal(LocalName);
266 if (!StringRef(*ValueOr).getAsInteger(10, Result))
268 diagnoseBadIntegerOption(
269 IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr);
284 template <
typename T>
285 std::enable_if_t<std::is_integral_v<T>, std::optional<T>>
286 getLocalOrGlobal(StringRef LocalName, std::optional<T> Default)
const {
287 std::optional<StringRef> ValueOr = get(LocalName);
288 bool IsGlobal =
false;
291 ValueOr = getLocalOrGlobal(LocalName);
296 if (ValueOr ==
"" || ValueOr ==
"none" || ValueOr ==
"null" ||
297 (std::is_unsigned_v<T> && ValueOr ==
"-1"))
299 if (!StringRef(*ValueOr).getAsInteger(10, Result))
301 diagnoseBadIntegerOption(
302 IsGlobal ? Twine(LocalName) : NamePrefix + LocalName, *ValueOr);
316 template <
typename T>
317 std::enable_if_t<std::is_integral_v<T>,
T>
318 getLocalOrGlobal(StringRef LocalName, T Default)
const {
319 return getLocalOrGlobal<T>(LocalName).value_or(Default);
334 template <
typename T>
335 std::enable_if_t<std::is_enum_v<T>, std::optional<T>>
336 get(StringRef LocalName)
const {
337 if (std::optional<int64_t> ValueOr =
338 getEnumInt(LocalName, typeEraseMapping<T>(),
false))
339 return static_cast<T>(*ValueOr);
355 template <
typename T>
356 std::enable_if_t<std::is_enum_v<T>,
T> get(StringRef LocalName,
358 return get<T>(LocalName).value_or(Default);
374 template <
typename T>
375 std::enable_if_t<std::is_enum_v<T>, std::optional<T>>
376 getLocalOrGlobal(StringRef LocalName)
const {
377 if (std::optional<int64_t> ValueOr =
378 getEnumInt(LocalName, typeEraseMapping<T>(),
true))
379 return static_cast<T>(*ValueOr);
396 template <
typename T>
397 std::enable_if_t<std::is_enum_v<T>,
T> getLocalOrGlobal(StringRef LocalName,
399 return getLocalOrGlobal<T>(LocalName).value_or(Default);
405 StringRef Value)
const;
409 template <
typename T>
410 std::enable_if_t<std::is_integral_v<T>>
413 if constexpr (std::is_signed_v<T>)
414 storeInt(Options, LocalName, Value);
416 storeUnsigned(Options, LocalName, Value);
422 template <
typename T>
423 std::enable_if_t<std::is_integral_v<T>>
425 std::optional<T> Value)
const {
427 store(Options, LocalName, *Value);
429 store(Options, LocalName,
"none");
437 template <
typename T>
438 std::enable_if_t<std::is_enum_v<T>>
441 ArrayRef<std::pair<T, StringRef>> Mapping =
442 OptionEnumMapping<T>::getEnumMapping();
443 auto Iter = llvm::find_if(
444 Mapping, [&](
const std::pair<T, StringRef> &NameAndEnum) {
445 return NameAndEnum.first ==
Value;
447 assert(Iter != Mapping.end() &&
"Unknown Case Value");
448 store(Options, LocalName, Iter->second);
452 using NameAndValue = std::pair<int64_t, StringRef>;
454 std::optional<int64_t> getEnumInt(StringRef LocalName,
455 ArrayRef<NameAndValue> Mapping,
456 bool CheckGlobal)
const;
458 template <
typename T>
459 std::enable_if_t<std::is_enum_v<T>, std::vector<NameAndValue>>
460 typeEraseMapping()
const {
461 ArrayRef<std::pair<T, StringRef>> Mapping =
462 OptionEnumMapping<T>::getEnumMapping();
463 std::vector<NameAndValue> Result;
464 Result.reserve(Mapping.size());
465 for (
auto &MappedItem : Mapping) {
466 Result.emplace_back(
static_cast<int64_t
>(MappedItem.first),
473 int64_t Value)
const;
476 StringRef LocalName, uint64_t Value)
const;
478 std::string NamePrefix;
480 ClangTidyContext *Context;
484 void run(
const ast_matchers::MatchFinder::MatchResult &Result)
override;
485 std::string CheckName;
486 ClangTidyContext *Context;
491 StringRef getCurrentMainFile()
const {
return Context->getCurrentFile(); }
493 const LangOptions &getLangOpts()
const {
return Context->getLangOpts(); }
496 bool areDiagsSelfContained()
const {
497 return Context->areDiagsSelfContained();
499 StringRef getID()
const override {
return CheckName; }
512ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName)
const;
524ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName)
const;
529void ClangTidyCheck::OptionsView::store<bool>(
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::StringMap< ClangTidyValue > OptionMap
llvm::StringMap< ClangTidyValue > OptionMap
This class should be specialized by any enum type that needs to be converted to and from an llvm::Str...
static ArrayRef< std::pair< T, StringRef > > getEnumMapping()=delete