@Override
  public @Nullable ObjectStubTree<?> build(@Nullable Project project,
                                           @NotNull VirtualFile vFile,
                                           @Nullable PsiFile psiFile) {
    try {
      byte[] content = vFile.contentsToByteArray();
      return vFile.computeWithPreloadedContentHint(content, () -> {
        FileContentImpl fc = (FileContentImpl)FileContentImpl.createByContent(vFile, content);
        if (project != null) {
          LOG.assertTrue(!project.isDefault());
          fc.setProject(project);
        }
        if (psiFile != null && !vFile.getFileType().isBinary()) {
          fc.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, psiFile.getViewProvider().getContents());
          // but don't reuse psiFile itself to avoid loading its contents. If we load AST, the stub will be thrown out anyway.
        }

        Stub element = RecursionManager.doPreventingRecursion(vFile, false, () -> StubTreeBuilder.buildStubTree(fc));
        ObjectStubTree<?> tree;
        if (element instanceof PsiFileStub) {
          tree = new StubTree((PsiFileStub<?>)element);
        }
        else {
          tree = element instanceof ObjectStubBase ? new ObjectStubTree<>((ObjectStubBase<?>)element, true) : null;
        }
        if (tree != null) {
          tree.setDebugInfo("created from file content");
          return tree;
        }
        return null;
      });
    }
    catch (IOException e) {
      if (LOG.isDebugEnabled()) {
        LOG.debug(e);
      }
      else {
        // content can be not cached yet, and the file can be deleted on disk already, without refresh
        LOG.info("Can't load file content for stub building: " + e.getMessage());
      }
    }

    return null;
  }
@Override
  public @Nullable ObjectStubTree<?> build(@Nullable Project project,
                                           @NotNull VirtualFile vFile,
                                           @Nullable PsiFile psiFile)