diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -27,6 +27,13 @@ namespace tidy { +/// This class should be specialized by any enum type that needs to be converted +/// to and from an \ref llvm::StringRef. +template struct OptionEnumMapping { + // Specializations of this struct must implement this function. + static ArrayRef> getEnumMapping() = delete; +}; + template class OptionError : public llvm::ErrorInfo { std::error_code convertToErrorCode() const override { return llvm::inconvertibleErrorCode(); @@ -313,36 +320,38 @@ } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the /// ``CheckOptions``. If the corresponding key is not present, returns a /// ``MissingOptionError``. If the key can't be 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 std::enable_if_t::value, llvm::Expected> - get(StringRef LocalName, ArrayRef> Mapping, - bool IgnoreCase = false) { - if (llvm::Expected ValueOr = getEnumInt( - LocalName, typeEraseMapping(Mapping), false, IgnoreCase)) + get(StringRef LocalName, bool IgnoreCase = false) { + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) return static_cast(*ValueOr); else return std::move(ValueOr.takeError()); } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// 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 /// 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 std::enable_if_t::value, T> - get(StringRef LocalName, ArrayRef> Mapping, - T Default, bool IgnoreCase = false) { - if (auto ValueOr = get(LocalName, Mapping, IgnoreCase)) + get(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = get(LocalName, IgnoreCase)) return *ValueOr; else logErrToStdErr(ValueOr.takeError()); @@ -350,40 +359,41 @@ } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from local or /// global ``CheckOptions``. Gets local option first. If local 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 /// 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 std::enable_if_t::value, llvm::Expected> getLocalOrGlobal(StringRef LocalName, - ArrayRef> Mapping, bool IgnoreCase = false) { - if (llvm::Expected ValueOr = getEnumInt( - LocalName, typeEraseMapping(Mapping), true, IgnoreCase)) + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) return static_cast(*ValueOr); else return std::move(ValueOr.takeError()); } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from local or /// global ``CheckOptions``. Gets local option first. If local 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. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> - getLocalOrGlobal(StringRef LocalName, - ArrayRef> Mapping, T Default, - bool IgnoreCase = false) { - if (auto ValueOr = getLocalOrGlobal(LocalName, Mapping, IgnoreCase)) + getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) return *ValueOr; else logErrToStdErr(ValueOr.takeError()); @@ -401,21 +411,25 @@ int64_t Value) const; /// Stores an option with the check-local name \p LocalName as the string - /// representation of the Enum \p Value using the \p Mapping to \p Options. + /// representation of the Enum \p Value 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 std::enable_if_t::value> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value, - ArrayRef> Mapping) { + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); auto Iter = llvm::find_if( - Mapping, [&](const std::pair &NameAndEnum) { - return NameAndEnum.second == Value; + Mapping, [&](const std::pair &NameAndEnum) { + return NameAndEnum.first == Value; }); assert(Iter != Mapping.end() && "Unknown Case Value"); - store(Options, LocalName, Iter->first); + store(Options, LocalName, Iter->second); } private: - using NameAndValue = std::pair; + using NameAndValue = std::pair; llvm::Expected getEnumInt(StringRef LocalName, ArrayRef Mapping, @@ -423,12 +437,14 @@ template std::enable_if_t::value, std::vector> - typeEraseMapping(ArrayRef> Mapping) { + typeEraseMapping() { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); std::vector Result; Result.reserve(Mapping.size()); for (auto &MappedItem : Mapping) { - Result.emplace_back(MappedItem.first, - static_cast(MappedItem.second)); + Result.emplace_back(static_cast(MappedItem.first), + MappedItem.second); } return Result; } diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -158,7 +158,7 @@ } llvm::Expected ClangTidyCheck::OptionsView::getEnumInt( - StringRef LocalName, ArrayRef> Mapping, + StringRef LocalName, ArrayRef> Mapping, bool CheckGlobal, bool IgnoreCase) { auto Iter = CheckOptions.find((NamePrefix + LocalName).str()); if (CheckGlobal && Iter == CheckOptions.end()) @@ -171,19 +171,19 @@ unsigned EditDistance = -1; for (const auto &NameAndEnum : Mapping) { if (IgnoreCase) { - if (Value.equals_lower(NameAndEnum.first)) - return NameAndEnum.second; - } else if (Value.equals(NameAndEnum.first)) { - return NameAndEnum.second; - } else if (Value.equals_lower(NameAndEnum.first)) { - Closest = NameAndEnum.first; + if (Value.equals_lower(NameAndEnum.second)) + return NameAndEnum.first; + } else if (Value.equals(NameAndEnum.second)) { + return NameAndEnum.first; + } else if (Value.equals_lower(NameAndEnum.second)) { + Closest = NameAndEnum.second; EditDistance = 0; continue; } - unsigned Distance = Value.edit_distance(NameAndEnum.first); + unsigned Distance = Value.edit_distance(NameAndEnum.second); if (Distance < EditDistance) { EditDistance = Distance; - Closest = NameAndEnum.first; + Closest = NameAndEnum.second; } } if (EditDistance < 3) diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp @@ -27,7 +27,6 @@ StringLikeClasses(utils::options::parseStringList( Options.get("StringLikeClasses", "::std::basic_string"))), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), AbseilStringsMatchHeader( Options.get("AbseilStringsMatchHeader", "absl/strings/match.h")) {} @@ -122,8 +121,7 @@ ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "StringLikeClasses", utils::options::serializeStringList(StringLikeClasses)); - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "AbseilStringsMatchHeader", AbseilStringsMatchHeader); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp @@ -25,13 +25,11 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), MathHeader(Options.get("MathHeader", "math.h")) {} void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "MathHeader", MathHeader); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp @@ -22,7 +22,6 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ProBoundsConstantArrayIndexCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -28,6 +28,31 @@ namespace clang { namespace tidy { + +template <> struct OptionEnumMapping { + static llvm::ArrayRef> + getEnumMapping() { + static constexpr std::pair + Mapping[] = {{modernize::Confidence::CL_Reasonable, "reasonable"}, + {modernize::Confidence::CL_Safe, "safe"}, + {modernize::Confidence::CL_Risky, "risky"}}; + return makeArrayRef(Mapping); + } +}; + +template <> struct OptionEnumMapping { + static llvm::ArrayRef< + std::pair> + getEnumMapping() { + static constexpr std::pair + 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 { static const char LoopNameArray[] = "forLoopArray"; @@ -44,25 +69,6 @@ static const char DerefByValueResultName[] = "derefByValueResult"; static const char DerefByRefResultName[] = "derefByRefResult"; -static ArrayRef> -getConfidenceMapping() { - static constexpr std::pair Mapping[] = { - {"reasonable", Confidence::CL_Reasonable}, - {"safe", Confidence::CL_Safe}, - {"risky", Confidence::CL_Risky}}; - return makeArrayRef(Mapping); -} - -static ArrayRef> -getStyleMapping() { - static constexpr std::pair Mapping[] = - {{"CamelCase", VariableNamer::NS_CamelCase}, - {"camelBack", VariableNamer::NS_CamelBack}, - {"lower_case", VariableNamer::NS_LowerCase}, - {"UPPER_CASE", VariableNamer::NS_UpperCase}}; - return makeArrayRef(Mapping); -} - // shared matchers static const TypeMatcher AnyType() { return anything(); } @@ -477,15 +483,13 @@ LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo), MaxCopySize(Options.get("MaxCopySize", 16ULL)), - MinConfidence(Options.get("MinConfidence", getConfidenceMapping(), - Confidence::CL_Reasonable)), - NamingStyle(Options.get("NamingStyle", getStyleMapping(), - VariableNamer::NS_CamelCase)) {} + MinConfidence(Options.get("MinConfidence", Confidence::CL_Reasonable)), + NamingStyle(Options.get("NamingStyle", VariableNamer::NS_CamelCase)) {} void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "MaxCopySize", std::to_string(MaxCopySize)); - Options.store(Opts, "MinConfidence", MinConfidence, getConfidenceMapping()); - Options.store(Opts, "NamingStyle", NamingStyle, getStyleMapping()); + Options.store(Opts, "MinConfidence", MinConfidence); + Options.store(Opts, "NamingStyle", NamingStyle); } void LoopConvertCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -45,7 +45,6 @@ StringRef MakeSmartPtrFunctionName) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), MakeSmartPtrFunctionHeader( Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), @@ -54,8 +53,7 @@ IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader); Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName); Options.store(Opts, "IgnoreMacros", IgnoreMacros); diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -121,13 +121,11 @@ PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), ValuesOnly(Options.get("ValuesOnly", false)) {} void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "ValuesOnly", ValuesOnly); } diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -75,12 +75,10 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -24,7 +24,6 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) { @@ -52,8 +51,7 @@ void ReplaceRandomShuffleCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp @@ -24,7 +24,6 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { @@ -97,8 +96,7 @@ } void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } } // namespace performance diff --git a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp @@ -32,7 +32,6 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void TypePromotionInMathFnCheck::registerPPCallbacks( @@ -44,8 +43,7 @@ void TypePromotionInMathFnCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -69,7 +69,6 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), AllowedTypes( utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} @@ -181,8 +180,7 @@ void UnnecessaryValueParamCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "AllowedTypes", utils::options::serializeStringList(AllowedTypes)); } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -75,6 +75,12 @@ }; } // namespace readability +template <> +struct OptionEnumMapping { + static llvm::ArrayRef< + std::pair> + getEnumMapping(); +}; } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -26,6 +26,26 @@ namespace clang { namespace tidy { + +llvm::ArrayRef< + std::pair> +OptionEnumMapping< + readability::IdentifierNamingCheck::CaseType>::getEnumMapping() { + static constexpr std::pair + 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 { // clang-format off @@ -99,16 +119,6 @@ #undef NAMING_KEYS // clang-format on -static constexpr std::pair - 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, ClangTidyContext *Context) : RenamerClangTidyCheck(Name, Context), @@ -117,7 +127,7 @@ for (auto const &Name : StyleNames) { auto CaseOptional = [&]() -> llvm::Optional { - auto ValueOr = Options.get((Name + "Case").str(), makeArrayRef(Mapping)); + auto ValueOr = Options.get((Name + "Case").str()); if (ValueOr) return *ValueOr; llvm::logAllUnhandledErrors( @@ -148,7 +158,7 @@ if (NamingStyles[i]) { if (NamingStyles[i]->Case) { Options.store(Opts, (StyleNames[i] + "Case").str(), - *NamingStyles[i]->Case, llvm::makeArrayRef(Mapping)); + *NamingStyles[i]->Case); } Options.store(Opts, (StyleNames[i] + "Prefix").str(), NamingStyles[i]->Prefix); diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h @@ -25,8 +25,6 @@ /// Supported include styles. enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 }; - static ArrayRef> getMapping(); - /// The classifications of inclusions, in the order they should be sorted. enum IncludeKinds { IK_MainTUInclude = 0, ///< e.g. ``#include "foo.h"`` when editing foo.cc @@ -66,6 +64,11 @@ }; } // namespace utils + +template <> struct OptionEnumMapping { + static ArrayRef> + getEnumMapping(); +}; } // namespace tidy } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -174,13 +174,14 @@ IncludeStmt); } -llvm::ArrayRef> -IncludeSorter::getMapping() { - static constexpr std::pair Mapping[] = - {{"llvm", IS_LLVM}, {"google", IS_Google}}; +} // namespace utils + +llvm::ArrayRef> +OptionEnumMapping::getEnumMapping() { + static constexpr std::pair + Mapping[] = {{utils::IncludeSorter::IS_LLVM, "llvm"}, + {utils::IncludeSorter::IS_Google, "google"}}; return makeArrayRef(Mapping); } - -} // namespace utils } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp @@ -32,7 +32,6 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), Rule(MakeRule(getLangOpts(), Options)), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - IncludeSorter::getMapping(), IncludeSorter::IS_LLVM)) { if (Rule) assert(llvm::all_of(Rule->Cases, hasExplanation) && @@ -45,7 +44,6 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), Rule(std::move(R)), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - IncludeSorter::getMapping(), IncludeSorter::IS_LLVM)) { assert(llvm::all_of(Rule->Cases, hasExplanation) && "clang-tidy checks must have an explanation by default;" @@ -111,8 +109,7 @@ void TransformerClangTidyCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } } // namespace utils diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp @@ -2,6 +2,8 @@ #include "ClangTidyTest.h" #include "gtest/gtest.h" +using namespace clang::ast_matchers; + namespace clang { namespace tidy { namespace test { @@ -10,21 +12,35 @@ public: TestCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override { - Finder->addMatcher(ast_matchers::varDecl().bind("var"), this); + void registerMatchers(MatchFinder *Finder) override { + Finder->addMatcher(varDecl().bind("var"), this); + DidRegister = true; } - void check(const ast_matchers::MatchFinder::MatchResult &Result) override { + void check(const MatchFinder::MatchResult &Result) override { const auto *Var = Result.Nodes.getNodeAs("var"); + + assert(Var && "Node isn't bound"); + DidFire = true; + // Add diagnostics in the wrong order. diag(Var->getLocation(), "variable"); diag(Var->getTypeSpecStartLoc(), "type specifier"); } + + ~TestCheck() { + assert(DidRegister && "Check never registered"); + assert(DidFire && "Check never fired"); + } + +private: + bool DidRegister = false; + bool DidFire = false; }; TEST(ClangTidyDiagnosticConsumer, SortsErrors) { std::vector Errors; runCheckOnCode("int a;", &Errors); - EXPECT_EQ(2ul, Errors.size()); + EXPECT_EQ(2u, Errors.size()); EXPECT_EQ("type specifier", Errors[0].Message.Message); EXPECT_EQ("variable", Errors[1].Message.Message); } diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -6,6 +6,20 @@ namespace clang { namespace tidy { + +enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; + +template <> struct OptionEnumMapping { + static llvm::ArrayRef> getEnumMapping() { + static constexpr std::pair 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 { TEST(ParseLineFilter, EmptyFilter) { @@ -209,15 +223,6 @@ } TEST(ValidConfiguration, ValidEnumOptions) { - - enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; - static constexpr std::pair 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; auto &CheckOptions = Options.CheckOptions; @@ -237,29 +242,30 @@ #define CHECK_ERROR_ENUM(Name, Expected) \ CHECK_ERROR(Name, UnparseableEnumOptionError, Expected) - CHECK_VAL(TestCheck.getLocal("Valid", Map), Colours::Red); - CHECK_VAL(TestCheck.getGlobal("GlobalValid", Map), Colours::Violet); - CHECK_VAL(TestCheck.getLocal("ValidWrongCase", Map, /*IgnoreCase*/ true), - Colours::Red); + CHECK_VAL(TestCheck.getIntLocal("Valid"), Colours::Red); + CHECK_VAL(TestCheck.getIntGlobal("GlobalValid"), Colours::Violet); CHECK_VAL( - TestCheck.getGlobal("GlobalValidWrongCase", Map, /*IgnoreCase*/ true), - Colours::Violet); - CHECK_ERROR_ENUM(TestCheck.getLocal("Invalid", Map), + TestCheck.getIntLocal("ValidWrongCase", /*IgnoreCase*/ true), + Colours::Red); + CHECK_VAL(TestCheck.getIntGlobal("GlobalValidWrongCase", + /*IgnoreCase*/ true), + Colours::Violet); + CHECK_ERROR_ENUM(TestCheck.getIntLocal("Invalid"), "invalid configuration value " "'Scarlet' for option 'test.Invalid'"); - CHECK_ERROR_ENUM(TestCheck.getLocal("ValidWrongCase", Map), + CHECK_ERROR_ENUM(TestCheck.getIntLocal("ValidWrongCase"), "invalid configuration value 'rED' for option " "'test.ValidWrongCase'; did you mean 'Red'?"); - CHECK_ERROR_ENUM(TestCheck.getLocal("NearMiss", Map), + CHECK_ERROR_ENUM(TestCheck.getIntLocal("NearMiss"), "invalid configuration value 'Oragne' for option " "'test.NearMiss'; did you mean 'Orange'?"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalInvalid", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalInvalid"), "invalid configuration value " "'Purple' for option 'GlobalInvalid'"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalValidWrongCase", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalValidWrongCase"), "invalid configuration value 'vIOLET' for option " "'GlobalValidWrongCase'; did you mean 'Violet'?"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalNearMiss", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalNearMiss"), "invalid configuration value 'Yelow' for option " "'GlobalNearMiss'; did you mean 'Yellow'?");