@Override
  @Nullable
  public ObjectStubTree readOrBuild(
      Project project, final VirtualFile vFile, @Nullable PsiFile psiFile) {
    final ObjectStubTree fromIndices = readFromVFile(project, vFile);
    if (fromIndices != null) {
      return fromIndices;
    }

    try {
      final FileContent fc = new FileContentImpl(vFile, vFile.contentsToByteArray());
      fc.putUserData(IndexingDataKeys.PROJECT, 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 = StubTreeBuilder.buildStubTree(fc);
      if (element instanceof PsiFileStub) {
        StubTree tree = new StubTree((PsiFileStub) element);
        tree.setDebugInfo("created from file content");
        return tree;
      }
    } catch (IOException e) {
      LOG.info(
          e); // content can be not cached yet, and the file can be deleted on disk already, without
              // refresh
    }

    return null;
  }
  @Override
  @Nullable
  public ObjectStubTree readOrBuild(
      Project project, final VirtualFile vFile, @Nullable PsiFile psiFile) {
    final ObjectStubTree fromIndices = readFromVFile(project, vFile);
    if (fromIndices != null) {
      return fromIndices;
    }

    if (!canHaveStub(vFile)) {
      return null;
    }

    try {
      final FileContent fc = new FileContentImpl(vFile, vFile.contentsToByteArray());
      fc.putUserData(IndexingDataKeys.PROJECT, project);
      if (psiFile != null) {
        fc.putUserData(IndexingDataKeys.PSI_FILE, psiFile);
        if (!vFile.getFileType().isBinary()) {
          fc.putUserData(
              IndexingDataKeys.FILE_TEXT_CONTENT_KEY, psiFile.getViewProvider().getContents());
        }
        psiFile.putUserData(PsiFileImpl.BUILDING_STUB, true);
      }
      Stub element;
      try {
        element = StubTreeBuilder.buildStubTree(fc);
      } finally {
        if (psiFile != null) {
          psiFile.putUserData(PsiFileImpl.BUILDING_STUB, null);
        }
      }
      if (element instanceof PsiFileStub) {
        StubTree tree = new StubTree((PsiFileStub) element);
        tree.setDebugInfo("created from file content, timestamp=" + vFile.getTimeStamp());
        return tree;
      }
    } catch (IOException e) {
      LOG.info(
          e); // content can be not cached yet, and the file can be deleted on disk already, without
      // refresh
    }

    return null;
  }