[clang-tidy] relanding b9306fd
authorNathan James <n.james93@hotmail.co.uk>
Mon, 29 Jun 2020 08:29:26 +0000 (09:29 +0100)
committerNathan James <n.james93@hotmail.co.uk>
Mon, 29 Jun 2020 08:29:39 +0000 (09:29 +0100)
Added some sanity checks to figure out the cause of a (seemingly unrelated) test failure on mac.
These can be removed should no issues arise on that platform again.

20 files changed:
clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
clang-tools-extra/clang-tidy/ClangTidyCheck.h
clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp
clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp
clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp
clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp
clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp
clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp
clang-tools-extra/clang-tidy/utils/IncludeSorter.h
clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp
clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp

index 7ddf054..39c0499 100644 (file)
@@ -158,7 +158,7 @@ void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options,
 }
 
 llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
-    StringRef LocalName, ArrayRef<std::pair<StringRef, int64_t>> Mapping,
+    StringRef LocalName, ArrayRef<std::pair<int64_t, StringRef>> Mapping,
     bool CheckGlobal, bool IgnoreCase) {
   auto Iter = CheckOptions.find((NamePrefix + LocalName).str());
   if (CheckGlobal && Iter == CheckOptions.end())
@@ -171,19 +171,19 @@ llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
   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)
index 84438c2..84ad16c 100644 (file)
@@ -27,6 +27,13 @@ class CompilerInstance;
 
 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> {
   std::error_code convertToErrorCode() const override {
     return llvm::inconvertibleErrorCode();
@@ -313,36 +320,38 @@ public:
     }
 
     /// 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 <typename T>
     std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
-    get(StringRef LocalName, ArrayRef<std::pair<StringRef, T>> Mapping,
-        bool IgnoreCase = false) {
-      if (llvm::Expected<int64_t> ValueOr = getEnumInt(
-              LocalName, typeEraseMapping(Mapping), false, IgnoreCase))
+    get(StringRef LocalName, bool IgnoreCase = false) {
+      if (llvm::Expected<int64_t> ValueOr =
+              getEnumInt(LocalName, typeEraseMapping<T>(), false, IgnoreCase))
         return static_cast<T>(*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 <typename T>
     std::enable_if_t<std::is_enum<T>::value, T>
-    get(StringRef LocalName, ArrayRef<std::pair<StringRef, T>> 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<T>(LocalName, IgnoreCase))
         return *ValueOr;
       else
         logErrToStdErr(ValueOr.takeError());
@@ -350,40 +359,41 @@ public:
     }
 
     /// 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 <typename T>
     std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
     getLocalOrGlobal(StringRef LocalName,
-                     ArrayRef<std::pair<StringRef, T>> Mapping,
                      bool IgnoreCase = false) {
-      if (llvm::Expected<int64_t> ValueOr = getEnumInt(
-              LocalName, typeEraseMapping(Mapping), true, IgnoreCase))
+      if (llvm::Expected<int64_t> ValueOr =
+              getEnumInt(LocalName, typeEraseMapping<T>(), true, IgnoreCase))
         return static_cast<T>(*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 <typename T>
     std::enable_if_t<std::is_enum<T>::value, T>
-    getLocalOrGlobal(StringRef LocalName,
-                     ArrayRef<std::pair<StringRef, T>> 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<T>(LocalName, IgnoreCase))
         return *ValueOr;
       else
         logErrToStdErr(ValueOr.takeError());
@@ -401,21 +411,25 @@ public:
                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 <typename T>
     std::enable_if_t<std::is_enum<T>::value>
-    store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value,
-          ArrayRef<std::pair<StringRef, T>> Mapping) {
+    store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) {
+      ArrayRef<std::pair<T, StringRef>> Mapping =
+          OptionEnumMapping<T>::getEnumMapping();
       auto Iter = llvm::find_if(
-          Mapping, [&](const std::pair<StringRef, T> &NameAndEnum) {
-            return NameAndEnum.second == Value;
+          Mapping, [&](const std::pair<T, StringRef> &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<StringRef, int64_t>;
+    using NameAndValue = std::pair<int64_t, StringRef>;
 
     llvm::Expected<int64_t> getEnumInt(StringRef LocalName,
                                        ArrayRef<NameAndValue> Mapping,
@@ -423,12 +437,14 @@ public:
 
     template <typename T>
     std::enable_if_t<std::is_enum<T>::value, std::vector<NameAndValue>>
-    typeEraseMapping(ArrayRef<std::pair<StringRef, T>> Mapping) {
+    typeEraseMapping() {
+      ArrayRef<std::pair<T, StringRef>> Mapping =
+          OptionEnumMapping<T>::getEnumMapping();
       std::vector<NameAndValue> Result;
       Result.reserve(Mapping.size());
       for (auto &MappedItem : Mapping) {
-        Result.emplace_back(MappedItem.first,
-                            static_cast<int64_t>(MappedItem.second));
+        Result.emplace_back(static_cast<int64_t>(MappedItem.first),
+                            MappedItem.second);
       }
       return Result;
     }
index 9539e28..7a8b71d 100644 (file)
@@ -27,7 +27,6 @@ StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name,
       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 @@ void StringFindStartswithCheck::storeOptions(
     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);
 }
 
index 608df8a..0864bb5 100644 (file)
@@ -25,13 +25,11 @@ InitVariablesCheck::InitVariablesCheck(StringRef Name,
                                        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);
 }
 
index b485112..dd0bedd 100644 (file)
@@ -22,7 +22,6 @@ ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
     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(
index dd18d86..720d43a 100644 (file)
@@ -28,6 +28,31 @@ using namespace llvm;
 
 namespace clang {
 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 {
 
 static const char LoopNameArray[] = "forLoopArray";
@@ -44,25 +69,6 @@ static const char EndVarName[] = "endVar";
 static const char DerefByValueResultName[] = "derefByValueResult";
 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
 static const TypeMatcher AnyType() { return anything(); }
 
@@ -477,15 +483,13 @@ LoopConvertCheck::RangeDescriptor::RangeDescriptor()
 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) {
index e34fd70..c677043 100644 (file)
@@ -45,7 +45,6 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
                                      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 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
       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);
index ed1a1a2..b6dedfb 100644 (file)
@@ -121,13 +121,11 @@ collectParamDecls(const CXXConstructorDecl *Ctor,
 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);
 }
 
index 295be20..f98254d 100644 (file)
@@ -75,12 +75,10 @@ ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef Name,
                                          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) {
index 9cfbd87..66917df 100644 (file)
@@ -24,7 +24,6 @@ ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name,
                                                      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::registerPPCallbacks(
 
 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) {
index d09673f..4cbb014 100644 (file)
@@ -24,7 +24,6 @@ MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name,
                                                    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::registerPPCallbacks(
 }
 
 void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "IncludeStyle", IncludeStyle,
-                utils::IncludeSorter::getMapping());
+  Options.store(Opts, "IncludeStyle", IncludeStyle);
 }
 
 } // namespace performance
index d08cec1..597445d 100644 (file)
@@ -32,7 +32,6 @@ TypePromotionInMathFnCheck::TypePromotionInMathFnCheck(
     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::registerPPCallbacks(
 
 void TypePromotionInMathFnCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "IncludeStyle", IncludeStyle,
-                utils::IncludeSorter::getMapping());
+  Options.store(Opts, "IncludeStyle", IncludeStyle);
 }
 
 void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) {
index 5b5f2ff..5de53b1 100644 (file)
@@ -69,7 +69,6 @@ UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
     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::registerPPCallbacks(
 
 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));
 }
index 6e7fcaa..c885aac 100644 (file)
@@ -26,6 +26,26 @@ using namespace clang::ast_matchers;
 
 namespace clang {
 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 {
 
 // clang-format off
@@ -99,16 +119,6 @@ static StringRef const StyleNames[] = {
 #undef NAMING_KEYS
 // 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,
                                              ClangTidyContext *Context)
     : RenamerClangTidyCheck(Name, Context),
@@ -117,7 +127,7 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
 
   for (auto const &Name : StyleNames) {
     auto CaseOptional = [&]() -> llvm::Optional<CaseType> {
-      auto ValueOr = Options.get((Name + "Case").str(), makeArrayRef(Mapping));
+      auto ValueOr = Options.get<CaseType>((Name + "Case").str());
       if (ValueOr)
         return *ValueOr;
       llvm::logAllUnhandledErrors(
@@ -148,7 +158,7 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
     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);
index 04bf53f..0f6c77b 100644 (file)
@@ -75,6 +75,12 @@ private:
 };
 
 } // namespace readability
+template <>
+struct OptionEnumMapping<readability::IdentifierNamingCheck::CaseType> {
+  static llvm::ArrayRef<
+      std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
+  getEnumMapping();
+};
 } // namespace tidy
 } // namespace clang
 
index 6013412..1ae8c29 100644 (file)
@@ -174,13 +174,14 @@ Optional<FixItHint> IncludeSorter::CreateIncludeInsertion(StringRef FileName,
                                     IncludeStmt);
 }
 
-llvm::ArrayRef<std::pair<StringRef, IncludeSorter::IncludeStyle>>
-IncludeSorter::getMapping() {
-  static constexpr std::pair<StringRef, IncludeSorter::IncludeStyle> Mapping[] =
-      {{"llvm", IS_LLVM}, {"google", IS_Google}};
+} // namespace utils
+
+llvm::ArrayRef<std::pair<utils::IncludeSorter::IncludeStyle, StringRef>>
+OptionEnumMapping<utils::IncludeSorter::IncludeStyle>::getEnumMapping() {
+  static constexpr std::pair<utils::IncludeSorter::IncludeStyle, StringRef>
+      Mapping[] = {{utils::IncludeSorter::IS_LLVM, "llvm"},
+                   {utils::IncludeSorter::IS_Google, "google"}};
   return makeArrayRef(Mapping);
 }
-
-} // namespace utils
 } // namespace tidy
 } // namespace clang
index 7dab2cc..1abe1b9 100644 (file)
@@ -25,8 +25,6 @@ public:
   /// Supported include styles.
   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.
   enum IncludeKinds {
     IK_MainTUInclude = 0,    ///< e.g. ``#include "foo.h"`` when editing foo.cc
@@ -66,6 +64,11 @@ private:
 };
 
 } // namespace utils
+
+template <> struct OptionEnumMapping<utils::IncludeSorter::IncludeStyle> {
+  static ArrayRef<std::pair<utils::IncludeSorter::IncludeStyle, StringRef>>
+  getEnumMapping();
+};
 } // namespace tidy
 } // namespace clang
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H
index 0a57856..4a7a418 100644 (file)
@@ -32,7 +32,6 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(
     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 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(RewriteRule R,
                                                      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::check(
 
 void TransformerClangTidyCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "IncludeStyle", IncludeStyle,
-                IncludeSorter::getMapping());
+  Options.store(Opts, "IncludeStyle", IncludeStyle);
 }
 
 } // namespace utils
index 2a4ed64..b3999a6 100644 (file)
@@ -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 @@ class TestCheck : public ClangTidyCheck {
 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<VarDecl>("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<ClangTidyError> Errors;
   runCheckOnCode<TestCheck>("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);
 }
index a089281..c4331f4 100644 (file)
@@ -6,6 +6,20 @@
 
 namespace clang {
 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 {
 
 TEST(ParseLineFilter, EmptyFilter) {
@@ -209,15 +223,6 @@ TEST(CheckOptionsValidation, ValidIntOptions) {
 }
 
 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;
   auto &CheckOptions = Options.CheckOptions;
 
@@ -237,29 +242,30 @@ TEST(ValidConfiguration, ValidEnumOptions) {
 #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<Colours>("Valid"), Colours::Red);
+  CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValid"), Colours::Violet);
   CHECK_VAL(
-      TestCheck.getGlobal("GlobalValidWrongCase", Map, /*IgnoreCase*/ true),
-      Colours::Violet);
-  CHECK_ERROR_ENUM(TestCheck.getLocal("Invalid", Map),
+      TestCheck.getIntLocal<Colours>("ValidWrongCase", /*IgnoreCase*/ true),
+      Colours::Red);
+  CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase",
+                                            /*IgnoreCase*/ true),
+            Colours::Violet);
+  CHECK_ERROR_ENUM(TestCheck.getIntLocal<Colours>("Invalid"),
                    "invalid configuration value "
                    "'Scarlet' for option 'test.Invalid'");
-  CHECK_ERROR_ENUM(TestCheck.getLocal("ValidWrongCase", Map),
+  CHECK_ERROR_ENUM(TestCheck.getIntLocal<Colours>("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<Colours>("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<Colours>("GlobalInvalid"),
                    "invalid configuration value "
                    "'Purple' for option 'GlobalInvalid'");
-  CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalValidWrongCase", Map),
+  CHECK_ERROR_ENUM(TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase"),
                    "invalid configuration value 'vIOLET' for option "
                    "'GlobalValidWrongCase'; did you mean 'Violet'?");
-  CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalNearMiss", Map),
+  CHECK_ERROR_ENUM(TestCheck.getIntGlobal<Colours>("GlobalNearMiss"),
                    "invalid configuration value 'Yelow' for option "
                    "'GlobalNearMiss'; did you mean 'Yellow'?");