diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt --- a/clang-tools-extra/clang-tidy/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/CMakeLists.txt @@ -10,6 +10,7 @@ ClangTidyOptions.cpp ClangTidyProfiling.cpp ExpandModularHeadersPPCallbacks.cpp + GlobList.cpp DEPENDS ClangSACheckers diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -17,7 +17,6 @@ #include "clang/Tooling/Refactoring.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Support/Regex.h" #include "llvm/Support/Timer.h" namespace clang { @@ -47,27 +46,6 @@ bool IsWarningAsError; }; -/// 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: - /// \p GlobList is a comma-separated list of globs (only '*' - /// metacharacter is supported) with optional '-' prefix to denote exclusion. - GlobList(StringRef Globs); - - /// 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 contains(StringRef S, bool Contains); - - bool Positive; - llvm::Regex Regex; - std::unique_ptr NextGlob; -}; - /// Contains displayed and ignored diagnostic counters for a ClangTidy /// run. struct ClangTidyStats { diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -17,6 +17,7 @@ #include "ClangTidyDiagnosticConsumer.h" #include "ClangTidyOptions.h" +#include "GlobList.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" @@ -118,47 +119,6 @@ : tooling::Diagnostic(CheckName, DiagLevel, BuildDirectory), IsWarningAsError(IsWarningAsError) {} -// Returns true if GlobList starts with the negative indicator ('-'), removes it -// from the GlobList. -static bool ConsumeNegativeIndicator(StringRef &GlobList) { - GlobList = GlobList.trim(" \r\n"); - if (GlobList.startswith("-")) { - GlobList = GlobList.substr(1); - return true; - } - return false; -} -// Converts first glob from the comma-separated list of globs to Regex and -// removes it and the trailing comma from the GlobList. -static llvm::Regex ConsumeGlob(StringRef &GlobList) { - StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(',')); - StringRef Glob = UntrimmedGlob.trim(' '); - GlobList = GlobList.substr(UntrimmedGlob.size() + 1); - SmallString<128> RegexText("^"); - StringRef MetaChars("()^$|*+?.[]\\{}"); - for (char C : Glob) { - if (C == '*') - RegexText.push_back('.'); - else if (MetaChars.find(C) != StringRef::npos) - RegexText.push_back('\\'); - RegexText.push_back(C); - } - RegexText.push_back('$'); - return llvm::Regex(RegexText); -} - -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; -} class ClangTidyContext::CachedGlobList { public: diff --git a/clang-tools-extra/clang-tidy/GlobList.h b/clang-tools-extra/clang-tidy/GlobList.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/GlobList.h @@ -0,0 +1,44 @@ +//===--- GlobList.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" +#include + +namespace clang { +namespace tidy { + +/// 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: + /// \p GlobList is a comma-separated list of globs (only '*' + /// metacharacter is supported) with optional '-' prefix to denote exclusion. + GlobList(StringRef Globs); + + /// 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 contains(StringRef S, bool Contains); + + bool Positive; + llvm::Regex Regex; + std::unique_ptr NextGlob; +}; + +} // end namespace tidy +} // end namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H diff --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/GlobList.cpp @@ -0,0 +1,56 @@ +//===--- tools/extra/clang-tidy/GlobList.cpp ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "GlobList.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang; +using namespace tidy; + +// Returns true if GlobList starts with the negative indicator ('-'), removes it +// from the GlobList. +static bool ConsumeNegativeIndicator(StringRef &GlobList) { + GlobList = GlobList.trim(" \r\n"); + if (GlobList.startswith("-")) { + GlobList = GlobList.substr(1); + return true; + } + return false; +} + +// Converts first glob from the comma-separated list of globs to Regex and +// removes it and the trailing comma from the GlobList. +static llvm::Regex ConsumeGlob(StringRef &GlobList) { + StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(',')); + StringRef Glob = UntrimmedGlob.trim(' '); + GlobList = GlobList.substr(UntrimmedGlob.size() + 1); + SmallString<128> RegexText("^"); + StringRef MetaChars("()^$|*+?.[]\\{}"); + for (char C : Glob) { + if (C == '*') + RegexText.push_back('.'); + else if (MetaChars.find(C) != StringRef::npos) + RegexText.push_back('\\'); + RegexText.push_back(C); + } + RegexText.push_back('$'); + return llvm::Regex(RegexText); +} + +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; +} diff --git a/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h --- a/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h +++ b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h @@ -10,8 +10,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H #include "../ClangTidyCheck.h" -#include "../ClangTidyDiagnosticConsumer.h" -#include "../utils/OptionsUtils.h" +#include "../GlobList.h" namespace clang { namespace tidy { diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -16,6 +16,7 @@ #include "../ClangTidy.h" #include "../ClangTidyForceLinker.h" +#include "../GlobList.h" #include "clang/Tooling/CommonOptionsParser.h" #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" diff --git a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt --- a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt +++ b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt @@ -10,6 +10,7 @@ ClangTidyDiagnosticConsumerTest.cpp ClangTidyOptionsTest.cpp IncludeInserterTest.cpp + GlobListTest.cpp GoogleModuleTest.cpp LLVMModuleTest.cpp NamespaceAliaserTest.cpp 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 @@ -29,66 +29,6 @@ EXPECT_EQ("variable", Errors[1].Message.Message); } -TEST(GlobList, Empty) { - GlobList Filter(""); - - EXPECT_TRUE(Filter.contains("")); - EXPECT_FALSE(Filter.contains("aaa")); -} - -TEST(GlobList, Nothing) { - GlobList Filter("-*"); - - EXPECT_FALSE(Filter.contains("")); - EXPECT_FALSE(Filter.contains("a")); - EXPECT_FALSE(Filter.contains("-*")); - EXPECT_FALSE(Filter.contains("-")); - EXPECT_FALSE(Filter.contains("*")); -} - -TEST(GlobList, Everything) { - GlobList Filter("*"); - - EXPECT_TRUE(Filter.contains("")); - EXPECT_TRUE(Filter.contains("aaaa")); - EXPECT_TRUE(Filter.contains("-*")); - EXPECT_TRUE(Filter.contains("-")); - EXPECT_TRUE(Filter.contains("*")); -} - -TEST(GlobList, Simple) { - GlobList Filter("aaa"); - - 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(GlobList, WhitespacesAtBegin) { - GlobList Filter("-*, a.b.*"); - - EXPECT_TRUE(Filter.contains("a.b.c")); - EXPECT_FALSE(Filter.contains("b.c")); -} - -TEST(GlobList, Complex) { - GlobList Filter("*,-a.*, -b.*, \r \n a.1.* ,-a.1.A.*,-..,-...,-..+,-*$, -*qwe* "); - - 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 } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/clang-tools-extra/unittests/clang-tidy/GlobListTest.cpp copy from clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp copy to clang-tools-extra/unittests/clang-tidy/GlobListTest.cpp --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/GlobListTest.cpp @@ -1,33 +1,8 @@ -#include "ClangTidy.h" -#include "ClangTidyTest.h" +#include "GlobList.h" #include "gtest/gtest.h" namespace clang { namespace tidy { -namespace test { - -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 check(const ast_matchers::MatchFinder::MatchResult &Result) override { - const auto *Var = Result.Nodes.getNodeAs("var"); - // Add diagnostics in the wrong order. - diag(Var->getLocation(), "variable"); - diag(Var->getTypeSpecStartLoc(), "type specifier"); - } -}; - -TEST(ClangTidyDiagnosticConsumer, SortsErrors) { - std::vector Errors; - runCheckOnCode("int a;", &Errors); - EXPECT_EQ(2ul, Errors.size()); - EXPECT_EQ("type specifier", Errors[0].Message.Message); - EXPECT_EQ("variable", Errors[1].Message.Message); -} TEST(GlobList, Empty) { GlobList Filter(""); @@ -89,6 +64,5 @@ EXPECT_TRUE(Filter.contains("asdfqwEasdf")); } -} // namespace test } // namespace tidy } // namespace clang