@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
  private static <K> void registerIndexer(final @NotNull StubIndexExtension<K, ?> extension, final boolean forceClean,
                                          @NotNull AsyncState state, @NotNull IndexVersionRegistrationSink registrationResultSink)
    throws IOException {
    final StubIndexKey<K, ?> indexKey = extension.getKey();
    final int version = extension.getVersion();
    FileBasedIndexExtension<K, Void> wrappedExtension = wrapStubIndexExtension(extension);

    Path indexRootDir = IndexInfrastructure.getIndexRootDir(indexKey);
    IndexVersion.IndexVersionDiff versionDiff = forceClean
                                                 ? new IndexVersion.IndexVersionDiff.InitialBuild(version)
                                                 : IndexVersion.versionDiffers(indexKey, version);

    registrationResultSink.setIndexVersionDiff(indexKey, versionDiff);
    if (versionDiff != IndexVersion.IndexVersionDiff.UP_TO_DATE) {
      FileUtil.deleteWithRenamingIfExists(indexRootDir);
      IndexVersion.rewriteVersion(indexKey, version);

      try {
        for (FileBasedIndexInfrastructureExtension ex : FileBasedIndexInfrastructureExtension.EP_NAME.getExtensionList()) {
          ex.onStubIndexVersionChanged(indexKey);
        }
      }
      catch (Exception e) {
        LOG.error(e);
      }
    }

    for (int attempt = 0; attempt < 2; attempt++) {
      try {
        UpdatableIndex<K, Void, FileContent, ?> index =
          TransientFileContentIndex.createIndex(wrappedExtension, new StubIndexStorageLayout<>(wrappedExtension, indexKey));

        for (FileBasedIndexInfrastructureExtension infrastructureExtension : FileBasedIndexInfrastructureExtension.EP_NAME.getExtensionList()) {
          UpdatableIndex<K, Void, FileContent, ?> intermediateIndex = infrastructureExtension.combineIndex(wrappedExtension, index);
          if (intermediateIndex != null) {
            index = intermediateIndex;
          }
        }

        synchronized (state) {
          state.myIndices.put(indexKey, index);
        }
        break;
      }
      catch (IOException e) {
        registrationResultSink.setIndexVersionDiff(indexKey, new IndexVersion.IndexVersionDiff.CorruptedRebuild(version));
        onExceptionInstantiatingIndex(indexKey, version, indexRootDir, e);
      }
      catch (RuntimeException e) {
        Throwable cause = FileBasedIndexEx.getCauseToRebuildIndex(e);
        if (cause == null) {
          throw e;
        }
        onExceptionInstantiatingIndex(indexKey, version, indexRootDir, e);
      }
    }
  }
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
  private static <K> void registerIndexer(final @NotNull StubIndexExtension<K, ?> extension, final boolean forceClean,
                                          @NotNull AsyncState state, @NotNull IndexVersionRegistrationSink registrationResultSink)