public void scheduleFileForIndexing(int fileId, @NotNull VirtualFile file, boolean onlyContentChanged, @NotNull List<Project> dirtyQueueProjects) {
    Set<Project> containingProjects = getContainingProjects(file);
    if (containingProjects.isEmpty() || !file.isValid() || (!file.isDirectory() && isTooLarge(file))) {
      // large file might be scheduled for update in before event when its size was not large
      doInvalidateIndicesForFile(fileId, file, containingProjects, dirtyQueueProjects);
      return;
    }
    myIndexableFilesFilterHolder.ensureFileIdPresent(fileId, () -> containingProjects);
    Project projectForFile = ContainerUtil.getFirstItem(containingProjects);

    var indexingRequest = projectForFile.getService(ProjectIndexingDependenciesService.class).getLatestIndexingRequestToken();
    var indexingStamp = indexingRequest.getFileIndexingStamp(file);

    List<ID<?, ?>> nontrivialFileIndexedStates = IndexingStamp.getNontrivialFileIndexedStates(fileId);

    // transient index value can depend on disk value because former is diff to latter
    // it doesn't matter content froze or not: indices might depend on file name too
    removeTransientFileDataFromIndices(nontrivialFileIndexedStates, fileId, file);

    IndexedFileImpl indexedFile = new IndexedFileImpl(file, projectForFile);

    // Apply index contentless indexes in-place
    // For 'normal indices' schedule the file for update and reset stamps for all affected indices (there
    // can be a client that used indices between before and after events, in such case indices are up-to-date due to force update
    // with old content)
    FileTypeManagerEx.getInstanceEx().freezeFileTypeTemporarilyIn(file, () -> {
      FileContent fileContent = new IndexedFileWrapper(indexedFile); // constructor is very light-weight, no need to burden with "lazy"

      // TODO-ank (IJPL-412): use UnindexedFilesFinder.getFileStatus instead
      Set<ID<?, ?>> indexesToInvalidate = new HashSet<>(nontrivialFileIndexedStates);
      for (ID<?, ?> indexId : getRequiredIndexes(indexedFile)) {
        if (tryIndexWithoutContent(indexId, file, fileId, fileContent, onlyContentChanged)) {
          indexesToInvalidate.remove(indexId); // IndexingStamp has been updated by applier just now
        }
        else {
          indexesToInvalidate.add(indexId);
        }
      }

      if (!indexesToInvalidate.isEmpty()) {
        for (ID<?, ?> indexId : indexesToInvalidate) {
          // TODO-ank: delete not needed indexed data now? (will be deleted during indexing)
          getIndex(indexId).invalidateIndexedStateForFile(fileId);
        }

        IndexingStamp.flushCache(fileId);
        getFilesToUpdateCollector().scheduleForUpdate(FileIndexingRequest.updateRequest(file), containingProjects,
                                                      ContainerUtil.union(dirtyQueueProjects, containingProjects));
      }
      else {
        IndexingFlag.setFileIndexed(file, indexingStamp);
      }
    });
  }
public void scheduleFileForIndexing(int fileId, @NotNull VirtualFile file, boolean onlyContentChanged, @NotNull List<Project> dirtyQueueProjects)