Revert "[clang-tidy] Reworked enum options handling(again)"

This reverts commit b9306fd042ce1c11d84f05d2124dfdc65b8331fe
and follow-up 42a51587c79a673045aec3586f4070630e5e7af3.

It seems to build check-clang-tools on macOS, see comments on
https://reviews.llvm.org/D82188
This commit is contained in:
Nico Weber 2020-06-28 21:49:07 -04:00
parent 80e15b4574
commit 8f73c4432b
19 changed files with 139 additions and 164 deletions

View File

@ -158,7 +158,7 @@ void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options,
} }
llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt( llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
StringRef LocalName, ArrayRef<std::pair<int64_t, StringRef>> Mapping, StringRef LocalName, ArrayRef<std::pair<StringRef, int64_t>> Mapping,
bool CheckGlobal, bool IgnoreCase) { bool CheckGlobal, bool IgnoreCase) {
auto Iter = CheckOptions.find((NamePrefix + LocalName).str()); auto Iter = CheckOptions.find((NamePrefix + LocalName).str());
if (CheckGlobal && Iter == CheckOptions.end()) if (CheckGlobal && Iter == CheckOptions.end())
@ -171,19 +171,19 @@ llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
unsigned EditDistance = -1; unsigned EditDistance = -1;
for (const auto &NameAndEnum : Mapping) { for (const auto &NameAndEnum : Mapping) {
if (IgnoreCase) { if (IgnoreCase) {
if (Value.equals_lower(NameAndEnum.second)) if (Value.equals_lower(NameAndEnum.first))
return NameAndEnum.first; return NameAndEnum.second;
} else if (Value.equals(NameAndEnum.second)) { } else if (Value.equals(NameAndEnum.first)) {
return NameAndEnum.first; return NameAndEnum.second;
} else if (Value.equals_lower(NameAndEnum.second)) { } else if (Value.equals_lower(NameAndEnum.first)) {
Closest = NameAndEnum.second; Closest = NameAndEnum.first;
EditDistance = 0; EditDistance = 0;
continue; continue;
} }
unsigned Distance = Value.edit_distance(NameAndEnum.second); unsigned Distance = Value.edit_distance(NameAndEnum.first);
if (Distance < EditDistance) { if (Distance < EditDistance) {
EditDistance = Distance; EditDistance = Distance;
Closest = NameAndEnum.second; Closest = NameAndEnum.first;
} }
} }
if (EditDistance < 3) if (EditDistance < 3)

View File

@ -27,13 +27,6 @@ class CompilerInstance;
namespace tidy { namespace tidy {
/// This class should be specialized by any enum type that needs to be converted
/// to and from an \ref llvm::StringRef.
template <class T> struct OptionEnumMapping {
// Specializations of this struct must implement this function.
static ArrayRef<std::pair<T, StringRef>> getEnumMapping() = delete;
};
template <typename T> class OptionError : public llvm::ErrorInfo<T> { template <typename T> class OptionError : public llvm::ErrorInfo<T> {
std::error_code convertToErrorCode() const override { std::error_code convertToErrorCode() const override {
return llvm::inconvertibleErrorCode(); return llvm::inconvertibleErrorCode();
@ -320,38 +313,36 @@ public:
} }
/// Read a named option from the ``Context`` and parse it as an /// Read a named option from the ``Context`` and parse it as an
/// enum type ``T``. /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
/// it will search the mapping ignoring the case.
/// ///
/// Reads the option with the check-local name \p LocalName from the /// Reads the option with the check-local name \p LocalName from the
/// ``CheckOptions``. If the corresponding key is not present, returns a /// ``CheckOptions``. If the corresponding key is not present, returns a
/// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a /// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a
/// ``UnparseableEnumOptionError``. /// ``UnparseableEnumOptionError``.
///
/// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
/// supply the mapping required to convert between ``T`` and a string.
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>> std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
get(StringRef LocalName, bool IgnoreCase = false) { get(StringRef LocalName, ArrayRef<std::pair<StringRef, T>> Mapping,
if (llvm::Expected<int64_t> ValueOr = bool IgnoreCase = false) {
getEnumInt(LocalName, typeEraseMapping<T>(), false, IgnoreCase)) if (llvm::Expected<int64_t> ValueOr = getEnumInt(
LocalName, typeEraseMapping(Mapping), false, IgnoreCase))
return static_cast<T>(*ValueOr); return static_cast<T>(*ValueOr);
else else
return std::move(ValueOr.takeError()); return std::move(ValueOr.takeError());
} }
/// Read a named option from the ``Context`` and parse it as an /// Read a named option from the ``Context`` and parse it as an
/// enum type ``T``. /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
/// it will search the mapping ignoring the case.
/// ///
/// Reads the option with the check-local name \p LocalName from the /// Reads the option with the check-local name \p LocalName from the
/// ``CheckOptions``. If the corresponding key is not present or it can't be /// ``CheckOptions``. If the corresponding key is not present or it can't be
/// parsed as a ``T``, returns \p Default. /// parsed as a ``T``, returns \p Default.
///
/// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
/// supply the mapping required to convert between ``T`` and a string.
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value, T> std::enable_if_t<std::is_enum<T>::value, T>
get(StringRef LocalName, T Default, bool IgnoreCase = false) { get(StringRef LocalName, ArrayRef<std::pair<StringRef, T>> Mapping,
if (auto ValueOr = get<T>(LocalName, IgnoreCase)) T Default, bool IgnoreCase = false) {
if (auto ValueOr = get(LocalName, Mapping, IgnoreCase))
return *ValueOr; return *ValueOr;
else else
logErrToStdErr(ValueOr.takeError()); logErrToStdErr(ValueOr.takeError());
@ -359,41 +350,40 @@ public:
} }
/// Read a named option from the ``Context`` and parse it as an /// Read a named option from the ``Context`` and parse it as an
/// enum type ``T``. /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
/// it will search the mapping ignoring the case.
/// ///
/// Reads the option with the check-local name \p LocalName from local or /// Reads the option with the check-local name \p LocalName from local or
/// global ``CheckOptions``. Gets local option first. If local is not /// global ``CheckOptions``. Gets local option first. If local is not
/// present, falls back to get global option. If global option is not /// present, falls back to get global option. If global option is not
/// present either, returns a ``MissingOptionError``. If the key can't be /// present either, returns a ``MissingOptionError``. If the key can't be
/// parsed as a ``T`` returns a ``UnparseableEnumOptionError``. /// parsed as a ``T`` returns a ``UnparseableEnumOptionError``.
///
/// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
/// supply the mapping required to convert between ``T`` and a string.
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>> std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
getLocalOrGlobal(StringRef LocalName, getLocalOrGlobal(StringRef LocalName,
ArrayRef<std::pair<StringRef, T>> Mapping,
bool IgnoreCase = false) { bool IgnoreCase = false) {
if (llvm::Expected<int64_t> ValueOr = if (llvm::Expected<int64_t> ValueOr = getEnumInt(
getEnumInt(LocalName, typeEraseMapping<T>(), true, IgnoreCase)) LocalName, typeEraseMapping(Mapping), true, IgnoreCase))
return static_cast<T>(*ValueOr); return static_cast<T>(*ValueOr);
else else
return std::move(ValueOr.takeError()); return std::move(ValueOr.takeError());
} }
/// Read a named option from the ``Context`` and parse it as an /// Read a named option from the ``Context`` and parse it as an
/// enum type ``T``. /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set,
/// it will search the mapping ignoring the case.
/// ///
/// Reads the option with the check-local name \p LocalName from local or /// Reads the option with the check-local name \p LocalName from local or
/// global ``CheckOptions``. Gets local option first. If local is not /// global ``CheckOptions``. Gets local option first. If local is not
/// present, falls back to get global option. If global option is not /// present, falls back to get global option. If global option is not
/// present either or it can't be parsed as a ``T``, returns \p Default. /// present either or it can't be parsed as a ``T``, returns \p Default.
///
/// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
/// supply the mapping required to convert between ``T`` and a string.
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value, T> std::enable_if_t<std::is_enum<T>::value, T>
getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) { getLocalOrGlobal(StringRef LocalName,
if (auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase)) ArrayRef<std::pair<StringRef, T>> Mapping, T Default,
bool IgnoreCase = false) {
if (auto ValueOr = getLocalOrGlobal(LocalName, Mapping, IgnoreCase))
return *ValueOr; return *ValueOr;
else else
logErrToStdErr(ValueOr.takeError()); logErrToStdErr(ValueOr.takeError());
@ -411,25 +401,21 @@ public:
int64_t Value) const; int64_t Value) const;
/// Stores an option with the check-local name \p LocalName as the string /// Stores an option with the check-local name \p LocalName as the string
/// representation of the Enum \p Value to \p Options. /// representation of the Enum \p Value using the \p Mapping to \p Options.
///
/// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
/// supply the mapping required to convert between ``T`` and a string.
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value> std::enable_if_t<std::is_enum<T>::value>
store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) { store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value,
ArrayRef<std::pair<T, StringRef>> Mapping = ArrayRef<std::pair<StringRef, T>> Mapping) {
OptionEnumMapping<T>::getEnumMapping();
auto Iter = llvm::find_if( auto Iter = llvm::find_if(
Mapping, [&](const std::pair<T, StringRef> &NameAndEnum) { Mapping, [&](const std::pair<StringRef, T> &NameAndEnum) {
return NameAndEnum.first == Value; return NameAndEnum.second == Value;
}); });
assert(Iter != Mapping.end() && "Unknown Case Value"); assert(Iter != Mapping.end() && "Unknown Case Value");
store(Options, LocalName, Iter->second); store(Options, LocalName, Iter->first);
} }
private: private:
using NameAndValue = std::pair<int64_t, StringRef>; using NameAndValue = std::pair<StringRef, int64_t>;
llvm::Expected<int64_t> getEnumInt(StringRef LocalName, llvm::Expected<int64_t> getEnumInt(StringRef LocalName,
ArrayRef<NameAndValue> Mapping, ArrayRef<NameAndValue> Mapping,
@ -437,14 +423,12 @@ public:
template <typename T> template <typename T>
std::enable_if_t<std::is_enum<T>::value, std::vector<NameAndValue>> std::enable_if_t<std::is_enum<T>::value, std::vector<NameAndValue>>
typeEraseMapping() { typeEraseMapping(ArrayRef<std::pair<StringRef, T>> Mapping) {
ArrayRef<std::pair<T, StringRef>> Mapping =
OptionEnumMapping<T>::getEnumMapping();
std::vector<NameAndValue> Result; std::vector<NameAndValue> Result;
Result.reserve(Mapping.size()); Result.reserve(Mapping.size());
for (auto &MappedItem : Mapping) { for (auto &MappedItem : Mapping) {
Result.emplace_back(static_cast<int64_t>(MappedItem.first), Result.emplace_back(MappedItem.first,
MappedItem.second); static_cast<int64_t>(MappedItem.second));
} }
return Result; return Result;
} }

View File

@ -27,6 +27,7 @@ StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name,
StringLikeClasses(utils::options::parseStringList( StringLikeClasses(utils::options::parseStringList(
Options.get("StringLikeClasses", "::std::basic_string"))), Options.get("StringLikeClasses", "::std::basic_string"))),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)), utils::IncludeSorter::IS_LLVM)),
AbseilStringsMatchHeader( AbseilStringsMatchHeader(
Options.get("AbseilStringsMatchHeader", "absl/strings/match.h")) {} Options.get("AbseilStringsMatchHeader", "absl/strings/match.h")) {}
@ -121,7 +122,8 @@ void StringFindStartswithCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "StringLikeClasses", Options.store(Opts, "StringLikeClasses",
utils::options::serializeStringList(StringLikeClasses)); utils::options::serializeStringList(StringLikeClasses));
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
Options.store(Opts, "AbseilStringsMatchHeader", AbseilStringsMatchHeader); Options.store(Opts, "AbseilStringsMatchHeader", AbseilStringsMatchHeader);
} }

View File

@ -25,11 +25,13 @@ InitVariablesCheck::InitVariablesCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)), utils::IncludeSorter::IS_LLVM)),
MathHeader(Options.get("MathHeader", "math.h")) {} MathHeader(Options.get("MathHeader", "math.h")) {}
void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
Options.store(Opts, "MathHeader", MathHeader); Options.store(Opts, "MathHeader", MathHeader);
} }

View File

@ -22,6 +22,7 @@ ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
StringRef Name, ClangTidyContext *Context) StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")), : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)) {} utils::IncludeSorter::IS_LLVM)) {}
void ProBoundsConstantArrayIndexCheck::storeOptions( void ProBoundsConstantArrayIndexCheck::storeOptions(

View File

@ -28,31 +28,6 @@ using namespace llvm;
namespace clang { namespace clang {
namespace tidy { namespace tidy {
template <> struct OptionEnumMapping<modernize::Confidence::Level> {
static llvm::ArrayRef<std::pair<modernize::Confidence::Level, StringRef>>
getEnumMapping() {
static constexpr std::pair<modernize::Confidence::Level, StringRef>
Mapping[] = {{modernize::Confidence::CL_Reasonable, "reasonable"},
{modernize::Confidence::CL_Safe, "safe"},
{modernize::Confidence::CL_Risky, "risky"}};
return makeArrayRef(Mapping);
}
};
template <> struct OptionEnumMapping<modernize::VariableNamer::NamingStyle> {
static llvm::ArrayRef<
std::pair<modernize::VariableNamer::NamingStyle, StringRef>>
getEnumMapping() {
static constexpr std::pair<modernize::VariableNamer::NamingStyle, StringRef>
Mapping[] = {{modernize::VariableNamer::NS_CamelCase, "CamelCase"},
{modernize::VariableNamer::NS_CamelBack, "camelBack"},
{modernize::VariableNamer::NS_LowerCase, "lower_case"},
{modernize::VariableNamer::NS_UpperCase, "UPPER_CASE"}};
return makeArrayRef(Mapping);
}
};
namespace modernize { namespace modernize {
static const char LoopNameArray[] = "forLoopArray"; static const char LoopNameArray[] = "forLoopArray";
@ -69,6 +44,25 @@ static const char EndVarName[] = "endVar";
static const char DerefByValueResultName[] = "derefByValueResult"; static const char DerefByValueResultName[] = "derefByValueResult";
static const char DerefByRefResultName[] = "derefByRefResult"; static const char DerefByRefResultName[] = "derefByRefResult";
static ArrayRef<std::pair<StringRef, Confidence::Level>>
getConfidenceMapping() {
static constexpr std::pair<StringRef, Confidence::Level> Mapping[] = {
{"reasonable", Confidence::CL_Reasonable},
{"safe", Confidence::CL_Safe},
{"risky", Confidence::CL_Risky}};
return makeArrayRef(Mapping);
}
static ArrayRef<std::pair<StringRef, VariableNamer::NamingStyle>>
getStyleMapping() {
static constexpr std::pair<StringRef, VariableNamer::NamingStyle> Mapping[] =
{{"CamelCase", VariableNamer::NS_CamelCase},
{"camelBack", VariableNamer::NS_CamelBack},
{"lower_case", VariableNamer::NS_LowerCase},
{"UPPER_CASE", VariableNamer::NS_UpperCase}};
return makeArrayRef(Mapping);
}
// shared matchers // shared matchers
static const TypeMatcher AnyType() { return anything(); } static const TypeMatcher AnyType() { return anything(); }
@ -483,13 +477,15 @@ LoopConvertCheck::RangeDescriptor::RangeDescriptor()
LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context) LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo), : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo),
MaxCopySize(Options.get("MaxCopySize", 16ULL)), MaxCopySize(Options.get("MaxCopySize", 16ULL)),
MinConfidence(Options.get("MinConfidence", Confidence::CL_Reasonable)), MinConfidence(Options.get("MinConfidence", getConfidenceMapping(),
NamingStyle(Options.get("NamingStyle", VariableNamer::NS_CamelCase)) {} Confidence::CL_Reasonable)),
NamingStyle(Options.get("NamingStyle", getStyleMapping(),
VariableNamer::NS_CamelCase)) {}
void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "MaxCopySize", std::to_string(MaxCopySize)); Options.store(Opts, "MaxCopySize", std::to_string(MaxCopySize));
Options.store(Opts, "MinConfidence", MinConfidence); Options.store(Opts, "MinConfidence", MinConfidence, getConfidenceMapping());
Options.store(Opts, "NamingStyle", NamingStyle); Options.store(Opts, "NamingStyle", NamingStyle, getStyleMapping());
} }
void LoopConvertCheck::registerMatchers(MatchFinder *Finder) { void LoopConvertCheck::registerMatchers(MatchFinder *Finder) {

View File

@ -45,6 +45,7 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
StringRef MakeSmartPtrFunctionName) StringRef MakeSmartPtrFunctionName)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)), utils::IncludeSorter::IS_LLVM)),
MakeSmartPtrFunctionHeader( MakeSmartPtrFunctionHeader(
Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)),
@ -53,7 +54,8 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader); Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader);
Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName); Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName);
Options.store(Opts, "IgnoreMacros", IgnoreMacros); Options.store(Opts, "IgnoreMacros", IgnoreMacros);

View File

@ -121,11 +121,13 @@ collectParamDecls(const CXXConstructorDecl *Ctor,
PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context) PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)), utils::IncludeSorter::IS_LLVM)),
ValuesOnly(Options.get("ValuesOnly", false)) {} ValuesOnly(Options.get("ValuesOnly", false)) {}
void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
Options.store(Opts, "ValuesOnly", ValuesOnly); Options.store(Opts, "ValuesOnly", ValuesOnly);
} }

View File

@ -75,10 +75,12 @@ ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)) {} utils::IncludeSorter::IS_LLVM)) {}
void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
} }
void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) {

View File

@ -24,6 +24,7 @@ ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)) {} utils::IncludeSorter::IS_LLVM)) {}
void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) { void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) {
@ -51,7 +52,8 @@ void ReplaceRandomShuffleCheck::registerPPCallbacks(
void ReplaceRandomShuffleCheck::storeOptions( void ReplaceRandomShuffleCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
} }
void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) { void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) {

View File

@ -24,6 +24,7 @@ MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)) {} utils::IncludeSorter::IS_LLVM)) {}
void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
@ -96,7 +97,8 @@ void MoveConstructorInitCheck::registerPPCallbacks(
} }
void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
} }
} // namespace performance } // namespace performance

View File

@ -32,6 +32,7 @@ TypePromotionInMathFnCheck::TypePromotionInMathFnCheck(
StringRef Name, ClangTidyContext *Context) StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)) {} utils::IncludeSorter::IS_LLVM)) {}
void TypePromotionInMathFnCheck::registerPPCallbacks( void TypePromotionInMathFnCheck::registerPPCallbacks(
@ -43,7 +44,8 @@ void TypePromotionInMathFnCheck::registerPPCallbacks(
void TypePromotionInMathFnCheck::storeOptions( void TypePromotionInMathFnCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
} }
void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) {

View File

@ -69,6 +69,7 @@ UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
StringRef Name, ClangTidyContext *Context) StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::getMapping(),
utils::IncludeSorter::IS_LLVM)), utils::IncludeSorter::IS_LLVM)),
AllowedTypes( AllowedTypes(
utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
@ -180,7 +181,8 @@ void UnnecessaryValueParamCheck::registerPPCallbacks(
void UnnecessaryValueParamCheck::storeOptions( void UnnecessaryValueParamCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
utils::IncludeSorter::getMapping());
Options.store(Opts, "AllowedTypes", Options.store(Opts, "AllowedTypes",
utils::options::serializeStringList(AllowedTypes)); utils::options::serializeStringList(AllowedTypes));
} }

View File

@ -26,26 +26,6 @@ using namespace clang::ast_matchers;
namespace clang { namespace clang {
namespace tidy { namespace tidy {
llvm::ArrayRef<
std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
OptionEnumMapping<
readability::IdentifierNamingCheck::CaseType>::getEnumMapping() {
static constexpr std::pair<readability::IdentifierNamingCheck::CaseType,
StringRef>
Mapping[] = {
{readability::IdentifierNamingCheck::CT_AnyCase, "aNy_CasE"},
{readability::IdentifierNamingCheck::CT_LowerCase, "lower_case"},
{readability::IdentifierNamingCheck::CT_UpperCase, "UPPER_CASE"},
{readability::IdentifierNamingCheck::CT_CamelBack, "camelBack"},
{readability::IdentifierNamingCheck::CT_CamelCase, "CamelCase"},
{readability::IdentifierNamingCheck::CT_CamelSnakeCase,
"Camel_Snake_Case"},
{readability::IdentifierNamingCheck::CT_CamelSnakeBack,
"camel_Snake_Back"}};
return llvm::makeArrayRef(Mapping);
}
namespace readability { namespace readability {
// clang-format off // clang-format off
@ -119,6 +99,16 @@ static StringRef const StyleNames[] = {
#undef NAMING_KEYS #undef NAMING_KEYS
// clang-format on // clang-format on
static constexpr std::pair<StringRef, IdentifierNamingCheck::CaseType>
Mapping[] = {
{"aNy_CasE", IdentifierNamingCheck::CT_AnyCase},
{"lower_case", IdentifierNamingCheck::CT_LowerCase},
{"UPPER_CASE", IdentifierNamingCheck::CT_UpperCase},
{"camelBack", IdentifierNamingCheck::CT_CamelBack},
{"CamelCase", IdentifierNamingCheck::CT_CamelCase},
{"Camel_Snake_Case", IdentifierNamingCheck::CT_CamelSnakeCase},
{"camel_Snake_Back", IdentifierNamingCheck::CT_CamelSnakeBack}};
IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: RenamerClangTidyCheck(Name, Context), : RenamerClangTidyCheck(Name, Context),
@ -127,7 +117,7 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
for (auto const &Name : StyleNames) { for (auto const &Name : StyleNames) {
auto CaseOptional = [&]() -> llvm::Optional<CaseType> { auto CaseOptional = [&]() -> llvm::Optional<CaseType> {
auto ValueOr = Options.get<CaseType>((Name + "Case").str()); auto ValueOr = Options.get((Name + "Case").str(), makeArrayRef(Mapping));
if (ValueOr) if (ValueOr)
return *ValueOr; return *ValueOr;
llvm::logAllUnhandledErrors( llvm::logAllUnhandledErrors(
@ -158,7 +148,7 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
if (NamingStyles[i]) { if (NamingStyles[i]) {
if (NamingStyles[i]->Case) { if (NamingStyles[i]->Case) {
Options.store(Opts, (StyleNames[i] + "Case").str(), Options.store(Opts, (StyleNames[i] + "Case").str(),
*NamingStyles[i]->Case); *NamingStyles[i]->Case, llvm::makeArrayRef(Mapping));
} }
Options.store(Opts, (StyleNames[i] + "Prefix").str(), Options.store(Opts, (StyleNames[i] + "Prefix").str(),
NamingStyles[i]->Prefix); NamingStyles[i]->Prefix);

View File

@ -75,13 +75,6 @@ private:
}; };
} // namespace readability } // namespace readability
template <>
struct OptionEnumMapping<
readability::IdentifierNamingCheck::CaseType> {
static llvm::ArrayRef<
std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
getEnumMapping();
};
} // namespace tidy } // namespace tidy
} // namespace clang } // namespace clang

View File

@ -174,14 +174,13 @@ Optional<FixItHint> IncludeSorter::CreateIncludeInsertion(StringRef FileName,
IncludeStmt); IncludeStmt);
} }
} // namespace utils llvm::ArrayRef<std::pair<StringRef, IncludeSorter::IncludeStyle>>
IncludeSorter::getMapping() {
llvm::ArrayRef<std::pair<utils::IncludeSorter::IncludeStyle, StringRef>> static constexpr std::pair<StringRef, IncludeSorter::IncludeStyle> Mapping[] =
OptionEnumMapping<utils::IncludeSorter::IncludeStyle>::getEnumMapping() { {{"llvm", IS_LLVM}, {"google", IS_Google}};
static constexpr std::pair<utils::IncludeSorter::IncludeStyle, StringRef>
Mapping[] = {{utils::IncludeSorter::IS_LLVM, "llvm"},
{utils::IncludeSorter::IS_Google, "google"}};
return makeArrayRef(Mapping); return makeArrayRef(Mapping);
} }
} // namespace utils
} // namespace tidy } // namespace tidy
} // namespace clang } // namespace clang

View File

@ -25,6 +25,8 @@ public:
/// Supported include styles. /// Supported include styles.
enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 }; enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 };
static ArrayRef<std::pair<StringRef, IncludeStyle>> getMapping();
/// The classifications of inclusions, in the order they should be sorted. /// The classifications of inclusions, in the order they should be sorted.
enum IncludeKinds { enum IncludeKinds {
IK_MainTUInclude = 0, ///< e.g. ``#include "foo.h"`` when editing foo.cc IK_MainTUInclude = 0, ///< e.g. ``#include "foo.h"`` when editing foo.cc
@ -64,11 +66,6 @@ private:
}; };
} // namespace utils } // namespace utils
template <> struct OptionEnumMapping<utils::IncludeSorter::IncludeStyle> {
static ArrayRef<std::pair<utils::IncludeSorter::IncludeStyle, StringRef>>
getEnumMapping();
};
} // namespace tidy } // namespace tidy
} // namespace clang } // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H

View File

@ -32,6 +32,7 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(
StringRef Name, ClangTidyContext *Context) StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), Rule(MakeRule(getLangOpts(), Options)), : ClangTidyCheck(Name, Context), Rule(MakeRule(getLangOpts(), Options)),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
IncludeSorter::getMapping(),
IncludeSorter::IS_LLVM)) { IncludeSorter::IS_LLVM)) {
if (Rule) if (Rule)
assert(llvm::all_of(Rule->Cases, hasExplanation) && assert(llvm::all_of(Rule->Cases, hasExplanation) &&
@ -44,6 +45,7 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(RewriteRule R,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), Rule(std::move(R)), : ClangTidyCheck(Name, Context), Rule(std::move(R)),
IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", IncludeStyle(Options.getLocalOrGlobal("IncludeStyle",
IncludeSorter::getMapping(),
IncludeSorter::IS_LLVM)) { IncludeSorter::IS_LLVM)) {
assert(llvm::all_of(Rule->Cases, hasExplanation) && assert(llvm::all_of(Rule->Cases, hasExplanation) &&
"clang-tidy checks must have an explanation by default;" "clang-tidy checks must have an explanation by default;"
@ -109,7 +111,8 @@ void TransformerClangTidyCheck::check(
void TransformerClangTidyCheck::storeOptions( void TransformerClangTidyCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) { ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "IncludeStyle", IncludeStyle,
IncludeSorter::getMapping());
} }
} // namespace utils } // namespace utils

View File

@ -6,20 +6,6 @@
namespace clang { namespace clang {
namespace tidy { namespace tidy {
enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet };
template <> struct OptionEnumMapping<Colours> {
static llvm::ArrayRef<std::pair<Colours, StringRef>> getEnumMapping() {
static constexpr std::pair<Colours, StringRef> Mapping[] = {
{Colours::Red, "Red"}, {Colours::Orange, "Orange"},
{Colours::Yellow, "Yellow"}, {Colours::Green, "Green"},
{Colours::Blue, "Blue"}, {Colours::Indigo, "Indigo"},
{Colours::Violet, "Violet"}};
return makeArrayRef(Mapping);
}
};
namespace test { namespace test {
TEST(ParseLineFilter, EmptyFilter) { TEST(ParseLineFilter, EmptyFilter) {
@ -223,6 +209,15 @@ TEST(CheckOptionsValidation, ValidIntOptions) {
} }
TEST(ValidConfiguration, ValidEnumOptions) { TEST(ValidConfiguration, ValidEnumOptions) {
enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet };
static constexpr std::pair<StringRef, Colours> Mapping[] = {
{"Red", Colours::Red}, {"Orange", Colours::Orange},
{"Yellow", Colours::Yellow}, {"Green", Colours::Green},
{"Blue", Colours::Blue}, {"Indigo", Colours::Indigo},
{"Violet", Colours::Violet}};
static const auto Map = makeArrayRef(Mapping);
ClangTidyOptions Options; ClangTidyOptions Options;
auto &CheckOptions = Options.CheckOptions; auto &CheckOptions = Options.CheckOptions;
@ -242,30 +237,29 @@ TEST(ValidConfiguration, ValidEnumOptions) {
#define CHECK_ERROR_ENUM(Name, Expected) \ #define CHECK_ERROR_ENUM(Name, Expected) \
CHECK_ERROR(Name, UnparseableEnumOptionError, Expected) CHECK_ERROR(Name, UnparseableEnumOptionError, Expected)
CHECK_VAL(TestCheck.getIntLocal<Colours>("Valid"), Colours::Red); CHECK_VAL(TestCheck.getLocal("Valid", Map), Colours::Red);
CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValid"), Colours::Violet); CHECK_VAL(TestCheck.getGlobal("GlobalValid", Map), Colours::Violet);
CHECK_VAL(TestCheck.getLocal("ValidWrongCase", Map, /*IgnoreCase*/ true),
Colours::Red);
CHECK_VAL( CHECK_VAL(
TestCheck.getIntLocal<Colours>("ValidWrongCase", /*IgnoreCase*/ true), TestCheck.getGlobal("GlobalValidWrongCase", Map, /*IgnoreCase*/ true),
Colours::Red); Colours::Violet);
CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase", CHECK_ERROR_ENUM(TestCheck.getLocal("Invalid", Map),
/*IgnoreCase*/ true),
Colours::Violet);
CHECK_ERROR_ENUM(TestCheck.getIntLocal<Colours>("Invalid"),
"invalid configuration value " "invalid configuration value "
"'Scarlet' for option 'test.Invalid'"); "'Scarlet' for option 'test.Invalid'");
CHECK_ERROR_ENUM(TestCheck.getIntLocal<Colours>("ValidWrongCase"), CHECK_ERROR_ENUM(TestCheck.getLocal("ValidWrongCase", Map),
"invalid configuration value 'rED' for option " "invalid configuration value 'rED' for option "
"'test.ValidWrongCase'; did you mean 'Red'?"); "'test.ValidWrongCase'; did you mean 'Red'?");
CHECK_ERROR_ENUM(TestCheck.getIntLocal<Colours>("NearMiss"), CHECK_ERROR_ENUM(TestCheck.getLocal("NearMiss", Map),
"invalid configuration value 'Oragne' for option " "invalid configuration value 'Oragne' for option "
"'test.NearMiss'; did you mean 'Orange'?"); "'test.NearMiss'; did you mean 'Orange'?");
CHECK_ERROR_ENUM(TestCheck.getIntGlobal<Colours>("GlobalInvalid"), CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalInvalid", Map),
"invalid configuration value " "invalid configuration value "
"'Purple' for option 'GlobalInvalid'"); "'Purple' for option 'GlobalInvalid'");
CHECK_ERROR_ENUM(TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase"), CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalValidWrongCase", Map),
"invalid configuration value 'vIOLET' for option " "invalid configuration value 'vIOLET' for option "
"'GlobalValidWrongCase'; did you mean 'Violet'?"); "'GlobalValidWrongCase'; did you mean 'Violet'?");
CHECK_ERROR_ENUM(TestCheck.getIntGlobal<Colours>("GlobalNearMiss"), CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalNearMiss", Map),
"invalid configuration value 'Yelow' for option " "invalid configuration value 'Yelow' for option "
"'GlobalNearMiss'; did you mean 'Yellow'?"); "'GlobalNearMiss'; did you mean 'Yellow'?");