@Override
  public @NotNull SingleEntryIndexer<SerializedStubTree> getIndexer() {
    return new SingleEntryCompositeIndexer<SerializedStubTree, StubBuilderType, String>(false) {
      @Override
      public boolean requiresContentForSubIndexerEvaluation(@NotNull IndexedFile file) {
        return StubTreeBuilder.requiresContentToFindBuilder(file.getFileType());
      }

      @Override
      public @Nullable StubBuilderType calculateSubIndexer(@NotNull IndexedFile file) {
        return StubTreeBuilder.getStubBuilderType(file, true);
      }

      @Override
      public @NotNull String getSubIndexerVersion(@NotNull StubBuilderType type) {
        mySerializationManager.initSerializers();
        return type.getVersion();
      }

      @Override
      public @NotNull KeyDescriptor<String> getSubIndexerVersionDescriptor() {
        return EnumeratorStringDescriptor.INSTANCE;
      }

      @Override
      protected @Nullable SerializedStubTree computeValue(@NotNull FileContent inputData) {
        StubBuilderType subIndexerType = calculateSubIndexer(inputData);
        if (subIndexerType == null) {
          if (LOG.isDebugEnabled()) {
            LOG.debug("Stub builder not found for " + inputData.getFile() + ", " + calculateIndexingStamp(inputData));
          }
          return null;
        }
        return computeValue(inputData, Objects.requireNonNull(subIndexerType));
      }

      @Override
      protected @Nullable SerializedStubTree computeValue(final @NotNull FileContent inputData, @NotNull StubBuilderType type) {
        try {
          SerializedStubTree prebuiltTree = findPrebuiltSerializedStubTree(inputData);
          if (prebuiltTree != null) {
            prebuiltTree = prebuiltTree.reSerialize(mySerializationManager, myStubIndexesExternalizer);
            if (DEBUG_PREBUILT_INDICES) {
              assertPrebuiltStubTreeMatchesActualTree(prebuiltTree, inputData, type);
            }
            return prebuiltTree;
          }
        } catch (ProcessCanceledException pce) {
          throw pce;
        } catch (Exception e) {
          LOG.error("Error while indexing: " + inputData.getFileName() + " using prebuilt stub index", e);
        }

        Stub stub;
        try {
          stub = StubTreeBuilder.buildStubTree(inputData, type);
        } catch (Exception e) {
          if (e instanceof ControlFlowException) ExceptionUtil.rethrowUnchecked(e);
          throw new MapReduceIndexMappingException(e, type.getClassToBlameInCaseOfException());
        }
        if (stub == null) {
          if (LOG.isDebugEnabled()) {
            LOG.debug("No stub present for " + inputData.getFile() + ", " + calculateIndexingStamp(inputData));
          }
          return null;
        }

        SerializedStubTree serializedStubTree;
        try {
          serializedStubTree = SerializedStubTree.serializeStub(stub, mySerializationManager, myStubIndexesExternalizer);
          if (IndexDebugProperties.DEBUG) {
            assertDeserializedStubMatchesOriginalStub(serializedStubTree, stub);
          }
          if (LOG.isDebugEnabled()) {
            LOG.debug("Stub is built for " + inputData.getFile() + ", " + calculateIndexingStamp(inputData));
          }
        } catch (Exception e) {
          if (e instanceof ControlFlowException) ExceptionUtil.rethrowUnchecked(e);
          ObjectStubSerializer<?, ? extends Stub> stubType = stub.getStubType();
          Class<?> classToBlame = stubType != null ? stubType.getClass() : stub.getClass();
          throw new MapReduceIndexMappingException(e, classToBlame);
        }
        return serializedStubTree;
      }
    };
  }
@Override
  public @NotNull SingleEntryIndexer<SerializedStubTree> getIndexer()