1 //===--- tools/extra/clang-tidy/GlobList.cpp ------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
13 namespace clang::tidy
{
15 // Returns true if GlobList starts with the negative indicator ('-'), removes it
17 static bool consumeNegativeIndicator(StringRef
&GlobList
) {
18 GlobList
= GlobList
.trim();
19 if (GlobList
.startswith("-")) {
20 GlobList
= GlobList
.substr(1);
26 // Converts first glob from the comma-separated list of globs to Regex and
27 // removes it and the trailing comma from the GlobList.
28 static llvm::Regex
consumeGlob(StringRef
&GlobList
) {
29 StringRef UntrimmedGlob
= GlobList
.substr(0, GlobList
.find_first_of(",\n"));
30 StringRef Glob
= UntrimmedGlob
.trim();
31 GlobList
= GlobList
.substr(UntrimmedGlob
.size() + 1);
32 SmallString
<128> RegexText("^");
33 StringRef
MetaChars("()^$|*+?.[]\\{}");
36 RegexText
.push_back('.');
37 else if (MetaChars
.contains(C
))
38 RegexText
.push_back('\\');
39 RegexText
.push_back(C
);
41 RegexText
.push_back('$');
42 return {RegexText
.str()};
45 GlobList::GlobList(StringRef Globs
, bool KeepNegativeGlobs
/* =true */) {
46 Items
.reserve(Globs
.count(',') + Globs
.count('\n') + 1);
49 Item
.IsPositive
= !consumeNegativeIndicator(Globs
);
50 Item
.Regex
= consumeGlob(Globs
);
51 if (Item
.IsPositive
|| KeepNegativeGlobs
)
52 Items
.push_back(std::move(Item
));
53 } while (!Globs
.empty());
56 bool GlobList::contains(StringRef S
) const {
57 // Iterating the container backwards as the last match determins if S is in
59 for (const GlobListItem
&Item
: llvm::reverse(Items
)) {
60 if (Item
.Regex
.match(S
))
61 return Item
.IsPositive
;
66 bool CachedGlobList::contains(StringRef S
) const {
67 auto Entry
= Cache
.try_emplace(S
);
68 bool &Value
= Entry
.first
->getValue();
69 // If the entry was just inserted, determine its required value.
71 Value
= GlobList::contains(S
);
75 } // namespace clang::tidy