@NotNull
  public GlobalSearchScope intersectWith(@NotNull final GlobalSearchScope scope) {
    if (scope.isSearchOutsideRootModel()) {
      return super.intersectWith(scope);
    }

    return scope;
  }
  @NotNull
  public GlobalSearchScope uniteWith(@NotNull final GlobalSearchScope scope) {
    if (scope.isSearchOutsideRootModel()) {
      return super.uniteWith(scope);
    }

    return this;
  }
  @NotNull
  private Collection<PsiFile> collectFilesInScope(
      @NotNull final Set<PsiFile> alreadySearched, final boolean skipIndexed) {
    SearchScope customScope = myFindModel.getCustomScope();
    final GlobalSearchScope globalCustomScope = toGlobal(customScope);

    final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
    final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());

    class EnumContentIterator implements ContentIterator {
      final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();

      @Override
      public boolean processFile(@NotNull final VirtualFile virtualFile) {
        ApplicationManager.getApplication()
            .runReadAction(
                new Runnable() {
                  @Override
                  public void run() {
                    ProgressManager.checkCanceled();
                    if (virtualFile.isDirectory()
                        || !virtualFile.isValid()
                        || !myFileMask.value(virtualFile)
                        || globalCustomScope != null && !globalCustomScope.contains(virtualFile)) {
                      return;
                    }

                    if (skipIndexed
                        && isCoveredByIndex(virtualFile)
                        && (fileIndex.isInContent(virtualFile)
                            || fileIndex.isInLibraryClasses(virtualFile)
                            || fileIndex.isInLibrarySource(virtualFile))) {
                      return;
                    }

                    PsiFile psiFile = myPsiManager.findFile(virtualFile);
                    if (psiFile != null
                        && !(psiFile instanceof PsiBinaryFile)
                        && !alreadySearched.contains(psiFile)) {
                      PsiFile sourceFile = (PsiFile) psiFile.getNavigationElement();
                      if (sourceFile != null) psiFile = sourceFile;
                      if (!psiFile.getFileType().isBinary()) {
                        myFiles.add(psiFile);
                      }
                    }
                  }

                  final FileBasedIndexImpl fileBasedIndex =
                      (FileBasedIndexImpl) FileBasedIndex.getInstance();

                  private boolean isCoveredByIndex(VirtualFile file) {
                    FileType fileType = file.getFileType();
                    if (hasTrigrams) {
                      return TrigramIndex.isIndexable(fileType)
                          && fileBasedIndex.isIndexingCandidate(file, TrigramIndex.INDEX_ID);
                    }
                    return IdIndex.isIndexable(fileType)
                        && fileBasedIndex.isIndexingCandidate(file, IdIndex.NAME);
                  }
                });
        return true;
      }

      @NotNull
      private Collection<PsiFile> getFiles() {
        return myFiles;
      }
    }

    final EnumContentIterator iterator = new EnumContentIterator();

    if (customScope instanceof LocalSearchScope) {
      for (VirtualFile file : getLocalScopeFiles((LocalSearchScope) customScope)) {
        iterator.processFile(file);
      }
    } else if (customScope
        instanceof
        Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope /
                    // FilesScope
      //noinspection unchecked
      for (VirtualFile file : (Iterable<VirtualFile>) customScope) {
        iterator.processFile(file);
      }
    } else if (myPsiDirectory != null) {
      ApplicationManager.getApplication()
          .runReadAction(
              new Runnable() {
                @Override
                public void run() {
                  if (myPsiDirectory.isValid()) {
                    addFilesUnderDirectory(myPsiDirectory, iterator);
                  }
                }
              });

      myFileIndex.iterateContentUnderDirectory(myPsiDirectory.getVirtualFile(), iterator);
    } else {
      boolean success = myFileIndex.iterateContent(iterator);
      if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
        final VirtualFile[] librarySources =
            ApplicationManager.getApplication()
                .runReadAction(
                    new Computable<VirtualFile[]>() {
                      @Override
                      public VirtualFile[] compute() {
                        OrderEnumerator enumerator =
                            myModule == null
                                ? OrderEnumerator.orderEntries(myProject)
                                : OrderEnumerator.orderEntries(myModule);
                        return enumerator
                            .withoutModuleSourceEntries()
                            .withoutDepModules()
                            .getSourceRoots();
                      }
                    });
        iterateAll(librarySources, globalCustomScope, iterator);
      }
    }
    return iterator.getFiles();
  }