ActionCallback (@NotNull DocumentationComponent component, @NotNull DocumentationCollector collector) { ActionCallback callback = collector.actionCallback != null ? collector.actionCallback : createActionCallback(); boolean wasEmpty = component.isEmpty(); if (wasEmpty) { component.setText(CodeInsightBundle.message("javadoc.fetching.progress"), null, collector.provider); } ModalityState modality = ModalityState.defaultModalityState(); String precalculatedDocumentation = myPrecalculatedDocumentation; myPrecalculatedDocumentation = null; myUpdateDocAlarm.addRequest(() -> { if (myProject.isDisposed()) return; LOG.debug("Started fetching documentation..."); PsiElement element = collector.getElement(true); if (element == null || !ReadAction.compute(() -> element.isValid())) { LOG.debug("Element for which documentation was requested is not available anymore"); ModalityUiUtil.invokeLaterIfNeeded(ModalityState.any(), () -> { component.setText(CodeInsightBundle.message("no.documentation.found"), null, collector.provider); }); callback.setDone(); return; } Language elementLanguage = ReadAction.compute(() -> element.getLanguage()); DocToolWindowManager toolWindowManager = DocToolWindowManager.LANGUAGE_MANAGER.forLanguage(elementLanguage); if (toolWindowManager != null) { if (collector.onAutoUpdate && !toolWindowManager.isAutoUpdateAvailable()) { callback.setDone(); return; } if (myToolWindow != null) { toolWindowManager.prepareForShowDocumentation(myToolWindow, this); } } component.startWait(); final @Nls String text; final DocumentationProvider provider; try { if (precalculatedDocumentation != null) { LOG.debug("Setting precalculated documentation:\n", precalculatedDocumentation); text = precalculatedDocumentation; PsiElement originalElement = getOriginalElement(collector, element); provider = ReadAction.compute(() -> getProviderFromElement(element, originalElement)); } else { text = collector.getDocumentation(); provider = collector.provider; } } catch (Throwable e) { LOG.info(e); ModalityUiUtil.invokeLaterIfNeeded(ModalityState.any(), () -> { //noinspection InstanceofCatchParameter String message = e instanceof IndexNotReadyException ? CodeInsightBundle.message("documentation.message.documentation.is.not.available") : CodeInsightBundle.message("javadoc.external.fetch.error.message"); component.setText(message, null, collector.provider); component.clearHistory(); callback.setDone(); }); return; } LOG.debug("Documentation fetched successfully:\n", text); final @Nls String decoratedText = ReadAction.compute(() -> { if (text == null) { return decorate(element, CodeInsightBundle.message("no.documentation.found"), null, provider); } else if (text.isEmpty()) { return null; } else if (precalculatedDocumentation != null) { return text; // text == precalculatedDocumentation in this case; don't decorate it } else { return decorate(element, text, collector.effectiveUrl, provider); } }); PsiDocumentManager.getInstance(myProject).performLaterWhenAllCommitted(modality, () -> { if (!element.isValid()) { LOG.debug("Element for which documentation was requested is not valid"); callback.setDone(); return; } if (text == null) { component.setText(decoratedText, element, provider); } else if (text.isEmpty()) { component.setText(component.getDecoratedText(), element, provider); } else { component.setData(element, decoratedText, collector.effectiveUrl, collector.ref, provider); } if (wasEmpty) { component.clearHistory(); } callback.setDone(); }); }, 10); return callback; }