1 //===--- tools/extra/clang-tidy/GlobList.cpp ------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "GlobList.h" 10 #include "llvm/ADT/SmallString.h" 11 12 using namespace clang; 13 using namespace tidy; 14 15 // Returns true if GlobList starts with the negative indicator ('-'), removes it 16 // from the GlobList. ConsumeNegativeIndicator(StringRef & GlobList)17static bool ConsumeNegativeIndicator(StringRef &GlobList) { 18 GlobList = GlobList.trim(" \r\n"); 19 if (GlobList.startswith("-")) { 20 GlobList = GlobList.substr(1); 21 return true; 22 } 23 return false; 24 } 25 26 // Converts first glob from the comma-separated list of globs to Regex and 27 // removes it and the trailing comma from the GlobList. ConsumeGlob(StringRef & GlobList)28static llvm::Regex ConsumeGlob(StringRef &GlobList) { 29 StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(',')); 30 StringRef Glob = UntrimmedGlob.trim(' '); 31 GlobList = GlobList.substr(UntrimmedGlob.size() + 1); 32 SmallString<128> RegexText("^"); 33 StringRef MetaChars("()^$|*+?.[]\\{}"); 34 for (char C : Glob) { 35 if (C == '*') 36 RegexText.push_back('.'); 37 else if (MetaChars.contains(C)) 38 RegexText.push_back('\\'); 39 RegexText.push_back(C); 40 } 41 RegexText.push_back('$'); 42 return llvm::Regex(RegexText); 43 } 44 GlobList(StringRef Globs)45GlobList::GlobList(StringRef Globs) { 46 Items.reserve(Globs.count(',') + 1); 47 do { 48 GlobListItem Item; 49 Item.IsPositive = !ConsumeNegativeIndicator(Globs); 50 Item.Regex = ConsumeGlob(Globs); 51 Items.push_back(std::move(Item)); 52 } while (!Globs.empty()); 53 } 54 contains(StringRef S) const55bool GlobList::contains(StringRef S) const { 56 // Iterating the container backwards as the last match determins if S is in 57 // the list. 58 for (const GlobListItem &Item : llvm::reverse(Items)) { 59 if (Item.Regex.match(S)) 60 return Item.IsPositive; 61 } 62 return false; 63 } 64