Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -103,11 +103,11 @@ StringRef File); /// \brief Get the list of enabled checks. - std::vector getCheckNames(ChecksFilter &Filter); + std::vector getCheckNames(GlobList &Filter); private: typedef std::vector > CheckersList; - CheckersList getCheckersControlList(ChecksFilter &Filter); + CheckersList getCheckersControlList(GlobList &Filter); ClangTidyContext &Context; std::unique_ptr CheckFactories; Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -213,7 +213,7 @@ Context.setASTContext(&Compiler.getASTContext()); std::vector> Checks; - ChecksFilter &Filter = Context.getChecksFilter(); + GlobList &Filter = Context.getChecksFilter(); CheckFactories->createChecks(Filter, Checks); std::unique_ptr Finder( @@ -252,10 +252,10 @@ } std::vector -ClangTidyASTConsumerFactory::getCheckNames(ChecksFilter &Filter) { +ClangTidyASTConsumerFactory::getCheckNames(GlobList &Filter) { std::vector CheckNames; for (const auto &CheckFactory : *CheckFactories) { - if (Filter.isCheckEnabled(CheckFactory.first)) + if (Filter.contains(CheckFactory.first)) CheckNames.push_back(CheckFactory.first); } @@ -267,7 +267,7 @@ } ClangTidyASTConsumerFactory::CheckersList -ClangTidyASTConsumerFactory::getCheckersControlList(ChecksFilter &Filter) { +ClangTidyASTConsumerFactory::getCheckersControlList(GlobList &Filter) { CheckersList List; bool AnalyzerChecksEnabled = false; @@ -275,7 +275,7 @@ std::string Checker((AnalyzerCheckNamePrefix + CheckName).str()); AnalyzerChecksEnabled = AnalyzerChecksEnabled || - (!CheckName.startswith("debug") && Filter.isCheckEnabled(Checker)); + (!CheckName.startswith("debug") && Filter.contains(Checker)); } if (AnalyzerChecksEnabled) { @@ -290,7 +290,7 @@ std::string Checker((AnalyzerCheckNamePrefix + CheckName).str()); if (CheckName.startswith("core") || - (!CheckName.startswith("debug") && Filter.isCheckEnabled(Checker))) + (!CheckName.startswith("debug") && Filter.contains(Checker))) List.push_back(std::make_pair(CheckName, true)); } } Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -65,24 +65,25 @@ Level DiagLevel; }; -/// \brief Filters checks by name. -class ChecksFilter { +/// \brief Read-only set of strings represented as a list of positive and +/// negative globs. Positive globs add all matched strings to the set, negative +/// globs remove them in the order of appearance in the list. +class GlobList { public: /// \brief \p GlobList is a comma-separated list of globs (only '*' /// metacharacter is supported) with optional '-' prefix to denote exclusion. - ChecksFilter(StringRef GlobList); + GlobList(StringRef Globs); - /// \brief Returns \c true if the check with the specified \p Name should be - /// enabled. The result is the last matching glob's Positive flag. If \p Name - /// is not matched by any globs, the check is not enabled. - bool isCheckEnabled(StringRef Name) { return isCheckEnabled(Name, false); } + /// \brief Returns \c true if the pattern matches \p S. The result is the last + /// matching glob's Positive flag. + bool contains(StringRef S) { return contains(S, false); } private: - bool isCheckEnabled(StringRef Name, bool Enabled); + bool contains(StringRef S, bool Contains); bool Positive; llvm::Regex Regex; - std::unique_ptr NextFilter; + std::unique_ptr NextGlob; }; /// \brief Contains displayed and ignored diagnostic counters for a ClangTidy @@ -145,7 +146,7 @@ StringRef getCheckName(unsigned DiagnosticID) const; /// \brief Returns check filter for the \c CurrentFile. - ChecksFilter &getChecksFilter(); + GlobList &getChecksFilter(); /// \brief Returns global options. const ClangTidyGlobalOptions &getGlobalOptions() const; @@ -179,7 +180,7 @@ std::unique_ptr OptionsProvider; std::string CurrentFile; - std::unique_ptr CheckFilter; + std::unique_ptr CheckFilter; ClangTidyStats Stats; Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -146,18 +146,18 @@ return llvm::Regex(RegexText); } -ChecksFilter::ChecksFilter(StringRef GlobList) - : Positive(!ConsumeNegativeIndicator(GlobList)), - Regex(ConsumeGlob(GlobList)), - NextFilter(GlobList.empty() ? nullptr : new ChecksFilter(GlobList)) {} - -bool ChecksFilter::isCheckEnabled(StringRef Name, bool Enabled) { - if (Regex.match(Name)) - Enabled = Positive; - - if (NextFilter) - Enabled = NextFilter->isCheckEnabled(Name, Enabled); - return Enabled; +GlobList::GlobList(StringRef Globs) + : Positive(!ConsumeNegativeIndicator(Globs)), + Regex(ConsumeGlob(Globs)), + NextGlob(Globs.empty() ? nullptr : new GlobList(Globs)) {} + +bool GlobList::contains(StringRef S, bool Contains) { + if (Regex.match(S)) + Contains = Positive; + + if (NextGlob) + Contains = NextGlob->contains(S, Contains); + return Contains; } ClangTidyContext::ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider) @@ -202,7 +202,7 @@ void ClangTidyContext::setCurrentFile(StringRef File) { CurrentFile = File; - CheckFilter.reset(new ChecksFilter(getOptions().Checks)); + CheckFilter.reset(new GlobList(getOptions().Checks)); } void ClangTidyContext::setASTContext(ASTContext *Context) { @@ -217,7 +217,7 @@ return OptionsProvider->getOptions(CurrentFile); } -ChecksFilter &ClangTidyContext::getChecksFilter() { +GlobList &ClangTidyContext::getChecksFilter() { assert(CheckFilter != nullptr); return *CheckFilter; } @@ -248,7 +248,7 @@ void ClangTidyDiagnosticConsumer::finalizeLastError() { if (!Errors.empty()) { ClangTidyError &Error = Errors.back(); - if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName) && + if (!Context.getChecksFilter().contains(Error.CheckName) && Error.DiagLevel != ClangTidyError::Error) { ++Context.Stats.ErrorsIgnoredCheckFilter; Errors.pop_back(); Index: clang-tidy/ClangTidyModule.h =================================================================== --- clang-tidy/ClangTidyModule.h +++ clang-tidy/ClangTidyModule.h @@ -86,7 +86,7 @@ /// store them in \p Checks. /// /// The caller takes ownership of the return \c ClangTidyChecks. - void createChecks(ChecksFilter &Filter, + void createChecks(GlobList &Filter, std::vector> &Checks); typedef std::map FactoryMap; Index: clang-tidy/ClangTidyModule.cpp =================================================================== --- clang-tidy/ClangTidyModule.cpp +++ clang-tidy/ClangTidyModule.cpp @@ -27,10 +27,9 @@ } void ClangTidyCheckFactories::createChecks( - ChecksFilter &Filter, - std::vector> &Checks) { + GlobList &Filter, std::vector> &Checks) { for (const auto &Factory : Factories) { - if (Filter.isCheckEnabled(Factory.first)) { + if (Filter.contains(Factory.first)) { ClangTidyCheck *Check = Factory.second->createCheck(); Check->setName(Factory.first); Checks.emplace_back(Check); Index: unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp =================================================================== --- unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp @@ -28,57 +28,57 @@ EXPECT_EQ("variable []", Errors[1].Message.Message); } -TEST(ChecksFilter, Empty) { - ChecksFilter Filter(""); +TEST(GlobList, Empty) { + GlobList Filter(""); - EXPECT_TRUE(Filter.isCheckEnabled("")); - EXPECT_FALSE(Filter.isCheckEnabled("aaa")); + EXPECT_TRUE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("aaa")); } -TEST(ChecksFilter, Nothing) { - ChecksFilter Filter("-*"); +TEST(GlobList, Nothing) { + GlobList Filter("-*"); - EXPECT_FALSE(Filter.isCheckEnabled("")); - EXPECT_FALSE(Filter.isCheckEnabled("a")); - EXPECT_FALSE(Filter.isCheckEnabled("-*")); - EXPECT_FALSE(Filter.isCheckEnabled("-")); - EXPECT_FALSE(Filter.isCheckEnabled("*")); + EXPECT_FALSE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("a")); + EXPECT_FALSE(Filter.contains("-*")); + EXPECT_FALSE(Filter.contains("-")); + EXPECT_FALSE(Filter.contains("*")); } -TEST(ChecksFilter, Everything) { - ChecksFilter Filter("*"); +TEST(GlobList, Everything) { + GlobList Filter("*"); - EXPECT_TRUE(Filter.isCheckEnabled("")); - EXPECT_TRUE(Filter.isCheckEnabled("aaaa")); - EXPECT_TRUE(Filter.isCheckEnabled("-*")); - EXPECT_TRUE(Filter.isCheckEnabled("-")); - EXPECT_TRUE(Filter.isCheckEnabled("*")); + EXPECT_TRUE(Filter.contains("")); + EXPECT_TRUE(Filter.contains("aaaa")); + EXPECT_TRUE(Filter.contains("-*")); + EXPECT_TRUE(Filter.contains("-")); + EXPECT_TRUE(Filter.contains("*")); } -TEST(ChecksFilter, Simple) { - ChecksFilter Filter("aaa"); +TEST(GlobList, Simple) { + GlobList Filter("aaa"); - EXPECT_TRUE(Filter.isCheckEnabled("aaa")); - EXPECT_FALSE(Filter.isCheckEnabled("")); - EXPECT_FALSE(Filter.isCheckEnabled("aa")); - EXPECT_FALSE(Filter.isCheckEnabled("aaaa")); - EXPECT_FALSE(Filter.isCheckEnabled("bbb")); + EXPECT_TRUE(Filter.contains("aaa")); + EXPECT_FALSE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("aa")); + EXPECT_FALSE(Filter.contains("aaaa")); + EXPECT_FALSE(Filter.contains("bbb")); } -TEST(ChecksFilter, Complex) { - ChecksFilter Filter("*,-a.*,-b.*,a.1.*,-a.1.A.*,-..,-...,-..+,-*$,-*qwe*"); +TEST(GlobList, Complex) { + GlobList Filter("*,-a.*,-b.*,a.1.*,-a.1.A.*,-..,-...,-..+,-*$,-*qwe*"); - EXPECT_TRUE(Filter.isCheckEnabled("aaa")); - EXPECT_TRUE(Filter.isCheckEnabled("qqq")); - EXPECT_FALSE(Filter.isCheckEnabled("a.")); - EXPECT_FALSE(Filter.isCheckEnabled("a.b")); - EXPECT_FALSE(Filter.isCheckEnabled("b.")); - EXPECT_FALSE(Filter.isCheckEnabled("b.b")); - EXPECT_TRUE(Filter.isCheckEnabled("a.1.b")); - EXPECT_FALSE(Filter.isCheckEnabled("a.1.A.a")); - EXPECT_FALSE(Filter.isCheckEnabled("qwe")); - EXPECT_FALSE(Filter.isCheckEnabled("asdfqweasdf")); - EXPECT_TRUE(Filter.isCheckEnabled("asdfqwEasdf")); + EXPECT_TRUE(Filter.contains("aaa")); + EXPECT_TRUE(Filter.contains("qqq")); + EXPECT_FALSE(Filter.contains("a.")); + EXPECT_FALSE(Filter.contains("a.b")); + EXPECT_FALSE(Filter.contains("b.")); + EXPECT_FALSE(Filter.contains("b.b")); + EXPECT_TRUE(Filter.contains("a.1.b")); + EXPECT_FALSE(Filter.contains("a.1.A.a")); + EXPECT_FALSE(Filter.contains("qwe")); + EXPECT_FALSE(Filter.contains("asdfqweasdf")); + EXPECT_TRUE(Filter.contains("asdfqwEasdf")); } } // namespace test