@Internal
  @Nullable("null in case index update is not needed") <FileIndexMetaData> SingleIndexValueApplier<FileIndexMetaData> createSingleIndexValueApplier(
    @NotNull ID<?, ?> indexId,
    @NotNull VirtualFile file,
    int inputId,
    @NotNull FileContent currentFC) {
    if (doTraceStubUpdates(indexId)) {
      LOG.info("index " + indexId + " update requested for " + getFileInfoLogString(inputId, file, currentFC));
    }
    if (!myRegisteredIndexes.isExtensionsDataLoaded()) reportUnexpectedAsyncInitState();
    if (!RebuildStatus.isOk(indexId) && !myIsUnitTestMode) {
      return null; // the index is scheduled for rebuild, no need to update
    }
    increaseLocalModCount();

    //noinspection unchecked
    UpdatableIndex<?, ?, FileContent, FileIndexMetaData> index = (UpdatableIndex<?, ?, FileContent, FileIndexMetaData>)getIndex(indexId);

    ensureFileBelongsToIndexableFilter(inputId, file);

    if (currentFC instanceof FileContentImpl &&
        FileBasedIndex.ourSnapshotMappingsEnabled &&
        (((FileBasedIndexExtension<?, ?>)index.getExtension()).hasSnapshotMapping() ||
         ((FileBasedIndexExtension<?, ?>)index.getExtension()).canBeShared())) {
      // Optimization: initialize indexed file hash eagerly. The hash is calculated by raw content bytes.
      // If we pass the currentFC to an indexer that calls "FileContentImpl.getContentAsText",
      // the raw bytes will be converted to text and assigned to null.
      // Then, to compute the hash, the reverse conversion will be necessary.
      // To avoid this extra conversion, let's initialize the hash eagerly.
      IndexedHashesSupport.getOrInitIndexedHash((FileContentImpl)currentFC);
    }

    markFileIndexed(file, currentFC);
    try {
      Supplier<Boolean> storageUpdate;
      long evaluatingIndexValueApplierTime = System.nanoTime();
      FileIndexMetaData fileIndexMetaData = index.getFileIndexMetaData(currentFC);
      try {
        storageUpdate = index.mapInputAndPrepareUpdate(inputId, currentFC);
      }
      catch (MapReduceIndexMappingException e) {
        index.setIndexedStateForFile(inputId, currentFC, false);
        BrokenIndexingDiagnostics.INSTANCE.getExceptionListener().onFileIndexMappingFailed(
          inputId,
          currentFC.getFile(),
          currentFC.getFileType(),
          indexId,
          e
        );
        return null;
      }
      finally {
        evaluatingIndexValueApplierTime = System.nanoTime() - evaluatingIndexValueApplierTime;
      }

      return new SingleIndexValueApplier<>(
        this,
        indexId,
        inputId,
        fileIndexMetaData,
        storageUpdate,
        file,
        currentFC,
        evaluatingIndexValueApplierTime
      );
    }
    catch (RuntimeException exception) {
      requestIndexRebuildOnException(exception, indexId);
      return null;
    }
    finally {
      unmarkBeingIndexed();
    }
  }
@Internal
  @Nullable("null in case index update is not needed") <FileIndexMetaData> SingleIndexValueApplier<FileIndexMetaData> createSingleIndexValueApplier(
    @NotNull ID<?, ?> indexId,
    @NotNull VirtualFile file,
    int inputId,
    @NotNull FileContent currentFC)