@Override
  public @Nullable String getToolTipText(MouseEvent event) {
    if (hovered == null) {
      return null;
    }

    if (!(hovered instanceof LazyTooltipCrumb) || !((LazyTooltipCrumb)hovered).needCalculateTooltip()) {
      return hovered.getTooltip();
    }

    final Crumb crumb = hovered;
    Promise<@NlsContexts.Tooltip String> tooltipLazy;
    synchronized (scheduledTooltipTasks) {
      tooltipLazy = scheduledTooltipTasks.get(crumb);
      if (tooltipLazy == null) {
        Runnable removeFinishedTask = () -> {
          synchronized (scheduledTooltipTasks) {
            scheduledTooltipTasks.remove(crumb);
          }
        };
        final IdeTooltipManager tooltipManager = IdeTooltipManager.getInstance();
        final Component component = event == null ? null : event.getComponent();
        tooltipLazy = ReadAction.nonBlocking(() -> crumb.getTooltip())
          .expireWhen(() -> !tooltipManager.isProcessing(component))
          .finishOnUiThread(ModalityState.any(), toolTipText -> tooltipManager.updateShownTooltip(component))
          .submit(AppExecutorUtil.getAppExecutorService())
          .onError(throwable -> {
            if (!(throwable instanceof CancellationException)) {
              LOG.error("Exception in LazyTooltipCrumb", throwable);
            }
            removeFinishedTask.run();
          })
          .onSuccess(toolTipText -> removeFinishedTask.run());
        scheduledTooltipTasks.put(crumb, tooltipLazy);
      }
    }
    if (tooltipLazy.isSucceeded()) {
      try {
        return tooltipLazy.blockingGet(0);
      }
      catch (TimeoutException | ExecutionException e) {
        LOG.error(e);
      }
    }
    return UIBundle.message("crumbs.calculating.tooltip");
  }
@Override
  public @Nullable String getToolTipText(MouseEvent event)