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 return GlobList
.consume_front("-");
22 // Extracts the first glob from the comma-separated list of globs,
23 // removes it and the trailing comma from the GlobList and
24 // returns the extracted glob.
25 static llvm::StringRef
extractNextGlob(StringRef
&GlobList
) {
26 StringRef UntrimmedGlob
= GlobList
.substr(0, GlobList
.find_first_of(",\n"));
27 StringRef Glob
= UntrimmedGlob
.trim();
28 GlobList
= GlobList
.substr(UntrimmedGlob
.size() + 1);
32 static llvm::Regex
createRegexFromGlob(StringRef
&Glob
) {
33 SmallString
<128> RegexText("^");
34 StringRef
MetaChars("()^$|*+?.[]\\{}");
37 RegexText
.push_back('.');
38 else if (MetaChars
.contains(C
))
39 RegexText
.push_back('\\');
40 RegexText
.push_back(C
);
42 RegexText
.push_back('$');
43 return {RegexText
.str()};
46 GlobList::GlobList(StringRef Globs
, bool KeepNegativeGlobs
/* =true */) {
47 Items
.reserve(Globs
.count(',') + Globs
.count('\n') + 1);
50 Item
.IsPositive
= !consumeNegativeIndicator(Globs
);
51 Item
.Text
= extractNextGlob(Globs
);
52 Item
.Regex
= createRegexFromGlob(Item
.Text
);
53 if (Item
.IsPositive
|| KeepNegativeGlobs
)
54 Items
.push_back(std::move(Item
));
55 } while (!Globs
.empty());
58 bool GlobList::contains(StringRef S
) const {
59 // Iterating the container backwards as the last match determins if S is in
61 for (const GlobListItem
&Item
: llvm::reverse(Items
)) {
62 if (Item
.Regex
.match(S
))
63 return Item
.IsPositive
;
68 bool CachedGlobList::contains(StringRef S
) const {
69 auto Entry
= Cache
.try_emplace(S
);
70 bool &Value
= Entry
.first
->getValue();
71 // If the entry was just inserted, determine its required value.
73 Value
= GlobList::contains(S
);
77 } // namespace clang::tidy