@Override
  @Nullable
  protected Runnable createRenewRequest(
      @NotNull final CoverageSuitesBundle suite, final @NotNull CoverageDataManager dataManager) {
    final ProjectData data = suite.getCoverageData();
    if (data == null) {
      return null;
    }

    return () -> {
      final Project project = getProject();

      final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);

      // find all modules content roots
      final VirtualFile[] modulesContentRoots =
          dataManager.doInReadActionIfProjectOpen(() -> rootManager.getContentRoots());

      if (modulesContentRoots == null) {
        return;
      }

      // gather coverage from all content roots
      for (VirtualFile root : modulesContentRoots) {
        annotate(
            root,
            suite,
            dataManager,
            data,
            project,
            new Annotator() {
              public void annotateSourceDirectory(
                  final String dirPath, final DirCoverageInfo info) {
                myDirCoverageInfos.put(dirPath, info);
              }

              public void annotateTestDirectory(final String dirPath, final DirCoverageInfo info) {
                myTestDirCoverageInfos.put(dirPath, info);
              }

              public void annotateFile(
                  @NotNull final String filePath, @NotNull final FileCoverageInfo info) {
                myFileCoverageInfos.put(filePath, info);
              }
            });
      }

      // final VirtualFile[] roots =
      // ProjectRootManagerEx.getInstanceEx(project).getContentRootsFromAllModules();
      // index.iterateContentUnderDirectory(roots[0], new ContentIterator() {
      //  public boolean processFile(final VirtualFile fileOrDir) {
      //    // TODO support for libraries and sdk
      //    if (index.isInContent(fileOrDir)) {
      //      final String normalizedPath = RubyCoverageEngine.rcovalizePath(fileOrDir.getPath(),
      // (RubyCoverageSuite)suite);
      //
      //      // TODO - check filters
      //
      //      if (fileOrDir.isDirectory()) {
      //        //// process dir
      //        //if (index.isInTestSourceContent(fileOrDir)) {
      //        //
      // //myTestDirCoverageInfos.put(RubyCoverageEngine.rcovalizePath(fileOrDir.getPath(),
      // (RubyCoverageSuite)suite), )
      //        //} else {
      //        //  myDirCoverageInfos.put(normalizedPath, new FileCoverageInfo());
      //        //}
      //      } else {
      //        // process file
      //        final ClassData classData = data.getOrCreateClassData(normalizedPath);
      //        if (classData != null) {
      //          final int count = classData.getLines().length;
      //          if (count != 0) {
      //            final FileCoverageInfo info = new FileCoverageInfo();
      //            info.totalLineCount = count;
      //            // let's count covered lines
      //            for (int i = 1; i <= count; i++) {
      //              final LineData lineData = classData.getLineData(i);
      //              if (lineData.getStatus() != LineCoverage.NONE){
      //                info.coveredLineCount++;
      //              }
      //            }
      //            myFileCoverageInfos.put(normalizedPath, info);
      //          }
      //        }
      //      }
      //    }
      //    return true;
      //  }
      // });

      dataManager.triggerPresentationUpdate();
    };
  }
  @Nullable
  protected DirCoverageInfo collectFolderCoverage(
      @NotNull final VirtualFile dir,
      final @NotNull CoverageDataManager dataManager,
      final Annotator annotator,
      final ProjectData projectInfo,
      boolean trackTestFolders,
      @NotNull final ProjectFileIndex index,
      @NotNull final CoverageEngine coverageEngine,
      Set<VirtualFile> visitedDirs,
      @NotNull final Map<String, String> normalizedFiles2Files) {
    if (!index.isInContent(dir)) {
      return null;
    }

    if (visitedDirs.contains(dir)) {
      return null;
    }

    if (!shouldCollectCoverageInsideLibraryDirs()) {
      if (index.isInLibrarySource(dir) || index.isInLibraryClasses(dir)) {
        return null;
      }
    }
    visitedDirs.add(dir);

    final boolean isInTestSrcContent = TestSourcesFilter.isTestSources(dir, getProject());

    // Don't count coverage for tests folders if track test folders is switched off
    if (!trackTestFolders && isInTestSrcContent) {
      return null;
    }

    final VirtualFile[] children = dataManager.doInReadActionIfProjectOpen(dir::getChildren);
    if (children == null) {
      return null;
    }

    final DirCoverageInfo dirCoverageInfo = new DirCoverageInfo();

    for (VirtualFile fileOrDir : children) {
      if (fileOrDir.isDirectory()) {
        final DirCoverageInfo childCoverageInfo =
            collectFolderCoverage(
                fileOrDir,
                dataManager,
                annotator,
                projectInfo,
                trackTestFolders,
                index,
                coverageEngine,
                visitedDirs,
                normalizedFiles2Files);

        if (childCoverageInfo != null) {
          dirCoverageInfo.totalFilesCount += childCoverageInfo.totalFilesCount;
          dirCoverageInfo.coveredFilesCount += childCoverageInfo.coveredFilesCount;
          dirCoverageInfo.totalLineCount += childCoverageInfo.totalLineCount;
          dirCoverageInfo.coveredLineCount += childCoverageInfo.coveredLineCount;
        }
      } else if (coverageEngine.coverageProjectViewStatisticsApplicableTo(fileOrDir)) {
        // let's count statistics only for ruby-based files

        final FileCoverageInfo fileInfo =
            collectBaseFileCoverage(fileOrDir, annotator, projectInfo, normalizedFiles2Files);

        if (fileInfo != null) {
          dirCoverageInfo.totalLineCount += fileInfo.totalLineCount;
          dirCoverageInfo.totalFilesCount++;

          if (fileInfo.coveredLineCount > 0) {
            dirCoverageInfo.coveredFilesCount++;
            dirCoverageInfo.coveredLineCount += fileInfo.coveredLineCount;
          }
        }
      }
    }

    // TODO - toplevelFilesCoverage - is unused variable!

    // no sense to include directories without ruby files
    if (dirCoverageInfo.totalFilesCount == 0) {
      return null;
    }

    final String dirPath = normalizeFilePath(dir.getPath());
    if (isInTestSrcContent) {
      annotator.annotateTestDirectory(dirPath, dirCoverageInfo);
    } else {
      annotator.annotateSourceDirectory(dirPath, dirCoverageInfo);
    }

    return dirCoverageInfo;
  }