@Nullable
  Set<String> findFileNamesMatchingIfCheap(char nextLetter, MinusculeMatcher matcher) {
    List<Pair<VirtualFile, String>> files = getMatchingRoots();
    Set<String> names = new HashSet<>();
    AtomicInteger counter = new AtomicInteger();
    BooleanSupplier tooMany = () -> counter.get() > 1000;
    for (Pair<VirtualFile, String> pair : files) {
      if (containsChar(pair.second, nextLetter) && matcher.matches(pair.second)) {
        names.add(pair.first.getName());
      } else {
        processProjectFilesUnder(pair.first, sub -> {
          counter.incrementAndGet();
          if (tooMany.getAsBoolean()) return false;

          String name = sub.getName();
          if (containsChar(name, nextLetter) && matcher.matches(name)) {
            names.add(name);
          }
          return true;
        });
      }
    }
    return tooMany.getAsBoolean() ? null : names;
  }
@Nullable
  Set<String> findFileNamesMatchingIfCheap(char nextLetter, MinusculeMatcher matcher)