@NotNull
  private RootInfo buildRootInfo(@NotNull Project project) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("Start building root info " + Thread.currentThread());
    }

    final RootInfo info = new RootInfo();
    ModuleManager moduleManager = ModuleManager.getInstance(project);
    boolean includeProjectJdk = true;

    for (final Module module : moduleManager.getModules()) {
      final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);

      for (ContentEntry contentEntry : moduleRootManager.getContentEntries()) {
        for (VirtualFile excludeRoot : contentEntry.getExcludeFolderFiles()) {
          if (!ensureValid(excludeRoot, contentEntry)) continue;

          info.excludedFromModule.put(excludeRoot, module);
        }
        VirtualFile contentRoot = contentEntry.getFile();
        if (contentRoot != null && ensureValid(contentRoot, module)) {
          if (!info.contentRootOf.containsKey(contentRoot)) {
            info.contentRootOf.put(contentRoot, module);
          }
          List<String> patterns = contentEntry.getExcludePatterns();
          if (!patterns.isEmpty()) {
            FileTypeAssocTable<Boolean> table = new FileTypeAssocTable<>();
            for (String pattern : patterns) {
              table.addAssociation(FileNameMatcherFactory.getInstance().createMatcher(pattern), Boolean.TRUE);
            }
            info.excludeFromContentRootTables.put(contentRoot, table);
          }
        }

        // Init module sources
        for (final SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
          VirtualFile sourceFolderRoot = sourceFolder.getFile();
          if (sourceFolderRoot != null && ensureValid(sourceFolderRoot, sourceFolder)) {
            info.classAndSourceRoots.add(sourceFolderRoot);
            info.sourceRootOf.putValue(sourceFolderRoot, module);
          }
        }
      }

      for (OrderEntry orderEntry : moduleRootManager.getOrderEntries()) {
        if (orderEntry instanceof LibraryOrSdkOrderEntry entry) {
          VirtualFile[] sourceRoots = entry.getRootFiles(OrderRootType.SOURCES);
          VirtualFile[] classRoots = entry.getRootFiles(OrderRootType.CLASSES);

          fillIndexWithLibraryRoots(info, entry, sourceRoots, classRoots);

          if (orderEntry instanceof LibraryOrderEntry) {
            Library library = ((LibraryOrderEntry)orderEntry).getLibrary();
            if (library != null) {
              for (VirtualFile root : ((LibraryEx)library).getExcludedRoots()) {
                if (!ensureValid(root, library)) continue;

                info.excludedFromLibraries.putValue(root, library);
              }
              for (VirtualFile root : sourceRoots) {
                if (!ensureValid(root, library)) continue;

                info.sourceOfLibraries.putValue(root, library);
              }
              for (VirtualFile root : classRoots) {
                if (!ensureValid(root, library)) continue;

                info.classOfLibraries.putValue(root, library);
              }
            }
          }
          else {
            includeProjectJdk = false;
          }
        }
      }
    }

    if (includeProjectJdk) {
      Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
      if (sdk != null) {
        fillIndexWithLibraryRoots(info, sdk, sdk.getRootProvider().getFiles(OrderRootType.SOURCES),
                                  sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
      }
    }

    for (AdditionalLibraryRootsProvider provider : AdditionalLibraryRootsProvider.EP_NAME.getExtensionList()) {
      Collection<SyntheticLibrary> libraries = provider.getAdditionalProjectLibraries(project);
      for (SyntheticLibrary library : libraries) {
        for (VirtualFile sourceRoot : library.getSourceRoots()) {
          sourceRoot = RootFileValidityChecker.correctRoot(sourceRoot, library, provider);
          if (sourceRoot == null) continue;

          info.libraryOrSdkSources.add(sourceRoot);
          info.classAndSourceRoots.add(sourceRoot);
          info.sourceOfLibraries.putValue(sourceRoot, library);
        }
        for (VirtualFile classRoot : library.getBinaryRoots()) {
          classRoot = RootFileValidityChecker.correctRoot(classRoot, library, provider);
          if (classRoot == null) continue;

          info.libraryOrSdkClasses.add(classRoot);
          info.classAndSourceRoots.add(classRoot);
          info.classOfLibraries.putValue(classRoot, library);
        }
        for (VirtualFile file : library.getExcludedRoots()) {
          file = RootFileValidityChecker.correctRoot(file, library, provider);
          if (file == null) continue;

          info.excludedFromLibraries.putValue(file, library);
        }
      }
    }

    for (DirectoryIndexExcludePolicy policy : DirectoryIndexExcludePolicy.EP_NAME.getExtensions(project)) {
      List<VirtualFile> files = ContainerUtil.mapNotNull(policy.getExcludeUrlsForProject(),
                                                         url -> VirtualFileManager.getInstance().findFileByUrl(url));
      info.excludedFromProject.addAll(ContainerUtil.filter(files, file -> RootFileValidityChecker.ensureValid(file, project, policy)));

      Function<Sdk, List<VirtualFile>> fun = policy.getExcludeSdkRootsStrategy();

      if (fun != null) {
        Set<Sdk> sdks = collectSdks();

        Set<VirtualFile> roots = collectSdkClasses(sdks);

        for (Sdk sdk: sdks) {
          for (VirtualFile file : fun.fun(sdk)) {
            if (!roots.contains(file)) {
              ContainerUtil.addIfNotNull(info.excludedFromSdkRoots, RootFileValidityChecker.correctRoot(file, sdk, policy));
            }
          }
        }
      }
    }
    for (UnloadedModuleDescription description : moduleManager.getUnloadedModuleDescriptions()) {
      for (VirtualFilePointer contentRootPointer : description.getContentRoots()) {
        VirtualFile contentRoot = contentRootPointer.getFile();
        if (contentRoot != null && ensureValid(contentRoot, description)) {
          info.contentRootOfUnloaded.put(contentRoot, description.getName());
        }
      }
    }

    return info;
  }
@NotNull
  private RootInfo buildRootInfo(@NotNull Project project)