79 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "GlobList.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallString.h"12 13namespace clang::tidy {14 15// Returns true if GlobList starts with the negative indicator ('-'), removes it16// from the GlobList.17static bool consumeNegativeIndicator(StringRef &GlobList) {18 GlobList = GlobList.trim();19 return GlobList.consume_front("-");20}21 22// Extracts the first glob from the comma-separated list of globs,23// removes it and the trailing comma from the GlobList and24// returns the extracted glob.25static llvm::StringRef extractNextGlob(StringRef &GlobList) {26 const StringRef UntrimmedGlob =27 GlobList.substr(0, GlobList.find_first_of(",\n"));28 const StringRef Glob = UntrimmedGlob.trim();29 GlobList = GlobList.substr(UntrimmedGlob.size() + 1);30 return Glob;31}32 33static llvm::Regex createRegexFromGlob(StringRef &Glob) {34 SmallString<128> RegexText("^");35 const StringRef MetaChars("()^$|*+?.[]\\{}");36 for (const char C : Glob) {37 if (C == '*')38 RegexText.push_back('.');39 else if (MetaChars.contains(C))40 RegexText.push_back('\\');41 RegexText.push_back(C);42 }43 RegexText.push_back('$');44 return {RegexText.str()};45}46 47GlobList::GlobList(StringRef Globs, bool KeepNegativeGlobs /* =true */) {48 Items.reserve(Globs.count(',') + Globs.count('\n') + 1);49 do {50 GlobListItem Item;51 Item.IsPositive = !consumeNegativeIndicator(Globs);52 Item.Text = extractNextGlob(Globs);53 Item.Regex = createRegexFromGlob(Item.Text);54 if (Item.IsPositive || KeepNegativeGlobs)55 Items.push_back(std::move(Item));56 } while (!Globs.empty());57}58 59bool GlobList::contains(StringRef S) const {60 // Iterating the container backwards as the last match determins if S is in61 // the list.62 for (const GlobListItem &Item : llvm::reverse(Items)) {63 if (Item.Regex.match(S))64 return Item.IsPositive;65 }66 return false;67}68 69bool CachedGlobList::contains(StringRef S) const {70 auto Entry = Cache.try_emplace(S);71 bool &Value = Entry.first->getValue();72 // If the entry was just inserted, determine its required value.73 if (Entry.second)74 Value = GlobList::contains(S);75 return Value;76}77 78} // namespace clang::tidy79