@NotNull
  public CompletableFuture<PsiElement> getTreeEvaluation(JavaValue value, DebuggerContextImpl context) throws EvaluateException {
    JavaValue parent = value.getParent();
    if (parent != null) {
      ValueDescriptorImpl vDescriptor = parent.getDescriptor();

      return vDescriptor.getTreeEvaluation(parent, context).thenCompose(parentEvaluation -> {
        if (!(parentEvaluation instanceof PsiExpression)) {
          return CompletableFuture.completedFuture(null);
        }

        return vDescriptor.getChildrenRenderer(context.getDebugProcess())
          .thenApply(childrenRenderer -> {
            try {
              return ReadAction.compute(() -> DebuggerTreeNodeExpression.substituteThis(
                childrenRenderer.getChildValueExpression(new DebuggerTreeNodeMock(value), context),
                ((PsiExpression)parentEvaluation), vDescriptor.getValue()
              ));
            }
            catch (EvaluateException e) {
              throw new CompletionException(e);
            }
          });
      });
    }

    Promise<PsiElement> res;
    try {
      PsiElement result = ReadAction.nonBlocking(() -> getDescriptorEvaluation(context)).executeSynchronously();
      res = Promises.resolvedPromise(result);
    }
    catch (Exception wrapper) {
      if (!(wrapper.getCause() instanceof EvaluateException)) throw wrapper;
      if (!(wrapper.getCause() instanceof NeedMarkException e)) throw (EvaluateException)wrapper.getCause();

      XValueMarkers<?, ?> markers = DebuggerUtilsImpl.getValueMarkers(context.getDebugProcess());
      if (markers != null) {
        ValueMarkup existing = markers.getMarkup(value);
        String markName;
        Promise<Object> promise;
        if (existing != null) {
          markName = existing.getText();
          promise = Promises.resolvedPromise();
        }
        else {
          markName = e.getMarkName();
          promise = markers.markValue(value, new ValueMarkup(markName, new JBColor(0, 0), null));
        }
        res = promise.then(__ -> ReadAction.nonBlocking(() -> JavaPsiFacade.getElementFactory(myProject)
          .createExpressionFromText(markName + CodeFragmentFactoryContextWrapper.DEBUG_LABEL_SUFFIX,
                                    PositionUtil.getContextElement(context))).executeSynchronously());
      }
      else {
        res = Promises.resolvedPromise(null);
      }
    }
    return Promises.asCompletableFuture(res);
  }
@NotNull
  public CompletableFuture<PsiElement> getTreeEvaluation(JavaValue value, DebuggerContextImpl context)