Moved GlobList into a separate header file

Summary:
It is a separate abstraction that is used in more contexts than just
a helper for ClangTidyDiagnosticConsumer.

Subscribers: mgorny, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66747

git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@369918 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clang-tidy/CMakeLists.txt b/clang-tidy/CMakeLists.txt
index cf84c24..220652d 100644
--- a/clang-tidy/CMakeLists.txt
+++ b/clang-tidy/CMakeLists.txt
@@ -10,6 +10,7 @@
   ClangTidyOptions.cpp
   ClangTidyProfiling.cpp
   ExpandModularHeadersPPCallbacks.cpp
+  GlobList.cpp
 
   DEPENDS
   ClangSACheckers
diff --git a/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index ef1c8ef..2889198 100644
--- a/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/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-tidy/ClangTidyDiagnosticConsumer.h b/clang-tidy/ClangTidyDiagnosticConsumer.h
index 793098a..10e3cca 100644
--- a/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/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<GlobList> NextGlob;
-};
-
 /// Contains displayed and ignored diagnostic counters for a ClangTidy
 /// run.
 struct ClangTidyStats {
diff --git a/clang-tidy/GlobList.cpp b/clang-tidy/GlobList.cpp
new file mode 100644
index 0000000..4a8b352
--- /dev/null
+++ b/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-tidy/GlobList.h b/clang-tidy/GlobList.h
new file mode 100644
index 0000000..8015ad7
--- /dev/null
+++ b/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 <memory>
+
+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<GlobList> NextGlob;
+};
+
+} // end namespace tidy
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GLOBLIST_H
diff --git a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
index 0539b73..a0fb9fa 100644
--- a/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h
+++ b/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-tidy/tool/ClangTidyMain.cpp b/clang-tidy/tool/ClangTidyMain.cpp
index a8ad9cd..df83de8 100644
--- a/clang-tidy/tool/ClangTidyMain.cpp
+++ b/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/unittests/clang-tidy/CMakeLists.txt b/unittests/clang-tidy/CMakeLists.txt
index 0d91c6e..93b49f5 100644
--- a/unittests/clang-tidy/CMakeLists.txt
+++ b/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/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
index 67f1dfd..2a4ed64 100644
--- a/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
+++ b/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/unittests/clang-tidy/GlobListTest.cpp b/unittests/clang-tidy/GlobListTest.cpp
new file mode 100644
index 0000000..2f5c4b5
--- /dev/null
+++ b/unittests/clang-tidy/GlobListTest.cpp
@@ -0,0 +1,68 @@
+#include "GlobList.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tidy {
+
+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 tidy
+} // namespace clang