GlobList.cpp 2.4 KB

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