CancellableHint (@NotNull final Project project, @NotNull final Editor editor, @NotNull final Point point, final ValueHintType type) { final XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession(); if (session == null) { return CancellableHint.resolved(null); } final XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator(); if (evaluator == null) { return CancellableHint.resolved(null); } int offset = AbstractValueHint.calculateOffset(editor, point); Document document = editor.getDocument(); // adjust offset to match with other actions, like go to declaration offset = TargetElementUtil.adjustOffset(PsiDocumentManager.getInstance(project).getPsiFile(document), document, offset); Promise<ExpressionInfo> infoPromise = getExpressionInfo(evaluator, project, type, editor, offset); Promise<AbstractValueHint> hintPromise = infoPromise .thenAsync(expressionInfo -> { AsyncPromise<AbstractValueHint> resultPromise = new AsyncPromise<>(); UIUtil.invokeLaterIfNeeded(() -> { int textLength = document.getTextLength(); if (expressionInfo == null) { resultPromise.setResult(null); return; } TextRange range = expressionInfo.getTextRange(); if (range.getStartOffset() > range.getEndOffset() || range.getStartOffset() < 0 || range.getEndOffset() > textLength) { LOG.error("invalid range: " + range + ", text length = " + textLength + ", evaluator: " + evaluator); resultPromise.setResult(null); return; } resultPromise.setResult(new XValueHint(project, editor, point, type, expressionInfo, evaluator, session, false)); }); return resultPromise; }); return new CancellableHint(hintPromise, infoPromise); }