Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -18,6 +18,7 @@ #include "clang/Tooling/Refactoring.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" #include #include #include @@ -47,22 +48,25 @@ /// Reads the option with the check-local name \p LocalName from the /// \c CheckOptions. If the corresponding key is not present, returns /// \p Default. - std::string get(StringRef LocalName, std::string Default) const; + std::string get(StringRef LocalName, StringRef Default) const; - /// \brief Read a named option from the \c Context and parse it as an integral - /// type \c T. + /// \brief Read a named option from the \c Context and parse it as any + /// type \c T that has ScalarTraits<>. /// /// Reads the option with the check-local name \p LocalName from the /// \c CheckOptions. If the corresponding key is not present, returns /// \p Default. template - typename std::enable_if::value, T>::type + typename std::enable_if::value, T>::type get(StringRef LocalName, T Default) const { - std::string Value = get(LocalName, ""); - T Result = Default; - if (!Value.empty()) - StringRef(Value).getAsInteger(10, Result); - return Result; + std::string String = get(LocalName, ""); + + T Value; + StringRef Result = + llvm::yaml::ScalarTraits::input(String, nullptr, Value); + if (!Result.empty()) + return Default; + return Value; } /// \brief Stores an option with the check-local name \p LocalName with string @@ -70,10 +74,17 @@ void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const; - /// \brief Stores an option with the check-local name \p LocalName with - /// \c int64_t value \p Value to \p Options. - void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, - int64_t Value) const; + /// \brief Stores an option with the check-local name \p LocalName of any + /// type that has ScalarTraits<>. + template + typename std::enable_if::value, void>::type + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, + const T &Value) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + llvm::yaml::ScalarTraits::output(Value, nullptr, Buffer); + store(Options, LocalName, Buffer.str()); + } private: std::string NamePrefix; Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -319,7 +319,7 @@ const ClangTidyOptions::OptionMap &CheckOptions) : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} -std::string OptionsView::get(StringRef LocalName, std::string Default) const { +std::string OptionsView::get(StringRef LocalName, StringRef Default) const { const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str()); if (Iter != CheckOptions.end()) return Iter->second; @@ -331,11 +331,6 @@ Options[NamePrefix + LocalName.str()] = Value; } -void OptionsView::store(ClangTidyOptions::OptionMap &Options, - StringRef LocalName, int64_t Value) const { - store(Options, LocalName, llvm::itostr(Value)); -} - std::vector getCheckNames(const ClangTidyOptions &Options) { clang::tidy::ClangTidyContext Context( llvm::make_unique(ClangTidyGlobalOptions(), Index: unittests/clang-tidy/ClangTidyOptionsTest.cpp =================================================================== --- unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -1,3 +1,4 @@ +#include "ClangTidy.h" #include "ClangTidyOptions.h" #include "gtest/gtest.h" @@ -54,7 +55,7 @@ EXPECT_EQ(1000u, Options.LineFilter[2].LineRanges[0].second); } -TEST(ParseConfiguration, ValidConfiguration) { +TEST(ParseConfiguration, BaseConfiguration) { llvm::ErrorOr Options = parseConfiguration("Checks: \"-*,misc-*\"\n" "HeaderFilterRegex: \".*\"\n" @@ -67,6 +68,33 @@ EXPECT_EQ("some.user", *Options->User); } +TEST(ParseConfiguration, CheckOptions) { + llvm::ErrorOr Options = + parseConfiguration("CheckOptions:\n" + " - key: test-check.String\n" + " value: ' qwe !@#* '\n" + " - key: test-check.IntegerPositive\n" + " value: 12345\n" + " - key: test-check.IntegerNegative\n" + " value: -67890\n" + " - key: test-check.BooleanTrue\n" + " value: true\n" + " - key: test-check.BooleanFalse\n" + " value: false\n" + ); + EXPECT_TRUE(!!Options); + OptionsView Opt("test-check", Options->CheckOptions); + EXPECT_EQ("qqq", Opt.get("NonExistent", "qqq")); + EXPECT_EQ(-123, Opt.get("NonExistent", -123)); + EXPECT_EQ(123U, Opt.get("NonExistent", 123U)); + EXPECT_EQ(" qwe !@#* ", Opt.get("String", "")); + EXPECT_EQ(12345, Opt.get("IntegerPositive", 0)); + EXPECT_EQ(12345U, Opt.get("IntegerPositive", 0U)); + EXPECT_EQ(-67890, Opt.get("IntegerNegative", 0)); + EXPECT_TRUE(Opt.get("BooleanTrue", false)); + EXPECT_FALSE(Opt.get("BooleanFalse", true)); +} + } // namespace test } // namespace tidy } // namespace clang