public static void findUsages(
     @NotNull FindModel findModel,
     @NotNull final Project project,
     @NotNull final Processor<UsageInfo> consumer,
     @NotNull FindUsagesProcessPresentation processPresentation) {
   findUsages(findModel, project, consumer, processPresentation, Collections.emptySet());
 }
  private static void logStats(Collection<PsiFile> otherFiles, long start) {
    long time = System.currentTimeMillis() - start;

    final Multiset<String> stats = HashMultiset.create();
    for (PsiFile file : otherFiles) {
      stats.add(
          StringUtil.notNullize(file.getViewProvider().getVirtualFile().getExtension())
              .toLowerCase());
    }

    List<String> extensions = ContainerUtil.newArrayList(stats.elementSet());
    Collections.sort(
        extensions,
        new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            return stats.count(o2) - stats.count(o1);
          }
        });

    String message =
        "Search in "
            + otherFiles.size()
            + " files with unknown types took "
            + time
            + "ms.\n"
            + "Mapping their extensions to an existing file type (e.g. Plain Text) might speed up the search.\n"
            + "Most frequent non-indexed file extensions: ";
    for (int i = 0; i < Math.min(10, extensions.size()); i++) {
      String extension = extensions.get(i);
      message += extension + "(" + stats.count(extension) + ") ";
    }
    LOG.info(message);
  }
  private static List<PsiElement> getTopLevelRegExpChars(String regExpText, Project project) {
    @SuppressWarnings("deprecation")
    PsiFile file = PsiFileFactory.getInstance(project).createFileFromText("A.regexp", regExpText);
    List<PsiElement> result = null;
    final PsiElement[] children = file.getChildren();

    for (PsiElement child : children) {
      PsiElement[] grandChildren = child.getChildren();
      if (grandChildren.length != 1)
        return Collections
            .emptyList(); // a | b, more than one branch, can not predict in current way

      for (PsiElement grandGrandChild : grandChildren[0].getChildren()) {
        if (result == null) result = new ArrayList<>();
        result.add(grandGrandChild);
      }
    }
    return result != null ? result : Collections.<PsiElement>emptyList();
  }
  @NotNull
  private Set<PsiFile> getFilesForFastWordSearch() {
    String stringToFind = myFindModel.getStringToFind();
    if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) {
      return Collections.emptySet();
    }

    SearchScope customScope = myFindModel.getCustomScope();
    GlobalSearchScope scope =
        myPsiDirectory != null
            ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true)
            : myModule != null
                ? myModule.getModuleContentScope()
                : customScope instanceof GlobalSearchScope
                    ? (GlobalSearchScope) customScope
                    : toGlobal(customScope);
    if (scope == null) {
      scope = ProjectScope.getContentScope(myProject);
    }

    final Set<PsiFile> resultFiles = new LinkedHashSet<PsiFile>();

    if (TrigramIndex.ENABLED) {
      final Set<Integer> keys = ContainerUtil.newTroveSet();
      TrigramBuilder.processTrigrams(
          stringToFind,
          new TrigramBuilder.TrigramProcessor() {
            @Override
            public boolean execute(int value) {
              keys.add(value);
              return true;
            }
          });

      if (!keys.isEmpty()) {
        final List<VirtualFile> hits = new ArrayList<VirtualFile>();
        final GlobalSearchScope finalScope = scope;
        ApplicationManager.getApplication()
            .runReadAction(
                new Runnable() {
                  @Override
                  public void run() {
                    FileBasedIndex.getInstance()
                        .getFilesWithKey(
                            TrigramIndex.INDEX_ID,
                            keys,
                            new CommonProcessors.CollectProcessor<VirtualFile>(hits),
                            finalScope);
                  }
                });

        for (VirtualFile hit : hits) {
          if (myFileMask.value(hit)) {
            PsiFile file = findFile(hit);
            if (file != null) {
              resultFiles.add(file);
            }
          }
        }

        return resultFiles;
      }
    }

    PsiSearchHelperImpl helper =
        (PsiSearchHelperImpl) PsiSearchHelper.SERVICE.getInstance(myProject);
    helper.processFilesWithText(
        scope,
        UsageSearchContext.ANY,
        myFindModel.isCaseSensitive(),
        stringToFind,
        new Processor<VirtualFile>() {
          @Override
          public boolean process(VirtualFile file) {
            if (myFileMask.value(file)) {
              ContainerUtil.addIfNotNull(resultFiles, findFile(file));
            }
            return true;
          }
        });

    // in case our word splitting is incorrect
    CacheManager cacheManager = CacheManager.SERVICE.getInstance(myProject);
    PsiFile[] filesWithWord =
        cacheManager.getFilesWithWord(
            stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive());
    for (PsiFile file : filesWithWord) {
      if (myFileMask.value(file.getVirtualFile())) {
        resultFiles.add(file);
      }
    }

    return resultFiles;
  }