EA-37556 - assert: RemoteProcessSupport.acquire

1. DocumentationProvider.generateDoc() contract is clarified;
2. Don't call DocumentationProvider.generateDoc() from EDT;
This commit is contained in:
Denis.Zhdanov
2012-07-20 13:19:27 +04:00
parent 05c59c4737
commit 5d5c55a876
3 changed files with 79 additions and 35 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,15 @@ public interface DocumentationProvider {
@Nullable
List<String> getUrlFor(PsiElement element, PsiElement originalElement);
/**
* Callback for asking the doc provider for the complete documentation.
* <p/>
* Underlying implementation may be time-consuming, that's why this method is expected not to be called from EDT.
*
* @param element target element which documentation is being requested
* @param originalElement element initially picked up from the current context
* @return target element's documentation (if any)
*/
@Nullable
String generateDoc(PsiElement element, PsiElement originalElement);
@@ -72,7 +72,10 @@ import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.LightweightHint;
import com.intellij.usageView.UsageViewShortNameLocation;
import com.intellij.usageView.UsageViewTypeLocation;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -168,7 +171,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return;
}
MouseEvent mouseEvent = e.getMouseEvent();
if (isMouseOverTooltip(mouseEvent.getLocationOnScreen()) || isMouseMovedTowardTooltip(mouseEvent.getLocationOnScreen())) {
myPrevMouseLocation = mouseEvent.getLocationOnScreen();
return;
@@ -212,6 +215,8 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
TextAttributesKey
.createTextAttributesKey("CTRL_CLICKABLE", new TextAttributes(Color.blue, null, Color.blue, EffectType.LINE_UNDERSCORE, 0));
@NotNull private final Alarm myDocAlarm;
public CtrlMouseHandler(final Project project, StartupManager startupManager, EditorColorsManager colorsManager,
FileEditorManager fileEditorManager, @NotNull DocumentationManager documentationManager,
@NotNull final EditorFactory editorFactory, @NotNull IdeTooltipManager tooltipManager)
@@ -234,6 +239,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
myFileEditorManager = fileEditorManager;
myDocumentationManager = documentationManager;
myTooltipManager = tooltipManager;
myDocAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, myProject);
}
@NotNull
@@ -265,7 +271,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
if (dx == 0) {
return mouseLocationOnScreen.x > bounds.x && mouseLocationOnScreen.x < bounds.x + bounds.width;
}
// Check if the mouse goes out of the control.
if (mouseLocationOnScreen.x < prevLocation.x && bounds.x > prevLocation.x) return false;
if (mouseLocationOnScreen.y < prevLocation.y && bounds.y > prevLocation.y) return false;
@@ -341,13 +347,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
private static DocInfo generateInfo(PsiElement element, PsiElement atPointer) {
final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer);
String result = doGenerateInfo(element, atPointer, documentationProvider);
if (result != null) {
String fullText = documentationProvider.generateDoc(element, atPointer);
String qName = element instanceof PsiQualifiedNamedElement ? ((PsiQualifiedNamedElement)element).getQualifiedName() : null;
String text = DocPreviewUtil.buildPreview(result, qName, fullText);
return new DocInfo(text, documentationProvider, element);
}
return DocInfo.EMPTY;
return result == null ? DocInfo.EMPTY : new DocInfo(result, documentationProvider, element);
}
@Nullable
@@ -611,6 +611,40 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
}
private void fulfillDocInfo(@NotNull final String header,
@NotNull final DocumentationProvider provider,
@NotNull final PsiElement originalElement,
@NotNull final PsiElement anchorElement,
@NotNull final Consumer<String> newTextConsumer)
{
myDocAlarm.cancelAllRequests();
myDocAlarm.addRequest(new Runnable() {
@Override
public void run() {
final Ref<String> fullTextRef = new Ref<String>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
fullTextRef.set(provider.generateDoc(anchorElement, originalElement));
}
});
String fullText = fullTextRef.get();
if (fullText == null) {
return;
}
String qName = anchorElement instanceof PsiQualifiedNamedElement ? ((PsiQualifiedNamedElement)anchorElement).getQualifiedName()
: null;
final String updatedText = DocPreviewUtil.buildPreview(header, qName, fullText);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
newTextConsumer.consume(updatedText);
}
});
}
}, 0);
}
private class TooltipProvider {
private final Editor myEditor;
private final LogicalPosition myPosition;
@@ -727,8 +761,14 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
pane.mouseExited(e);
}
}
};
JComponent label = HintUtil.createInformationLabel(docInfo.text, hyperlinkListener, mouseListener);
};
Ref<Consumer<String>> newTextConsumerRef = new Ref<Consumer<String>>();
JComponent label = HintUtil.createInformationLabel(docInfo.text, hyperlinkListener, mouseListener, newTextConsumerRef);
Consumer<String> newTextConsumer = newTextConsumerRef.get();
myDocAlarm.cancelAllRequests();
if (newTextConsumer != null && docInfo.docProvider != null && docInfo.documentationAnchor != null) {
fulfillDocInfo(docInfo.text, docInfo.docProvider, info.myElementAtPointer, docInfo.documentationAnchor, newTextConsumer);
}
QuickDocInfoPane quickDocPane = null;
if (docInfo.documentationAnchor != null) {
quickDocPane = new QuickDocInfoPane(docInfo.documentationAnchor, info.myElementAtPointer, label);
@@ -744,7 +784,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
0, false, HintManagerImpl.createHintHint(myEditor, p, hint, HintManager.ABOVE).setContentActive(false));
}
}
private HighlightersSet installHighlighterSet(Info info, Editor editor) {
final JComponent internalComponent = editor.getContentComponent();
internalComponent.addKeyListener(myEditorKeyListener);
@@ -875,7 +915,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
if (myDocumentationManager.hasActiveDockedDocWindow()) {
return;
}
// Skip event triggered when mouse leaves action button area.
if (!mouseEntered && new Rectangle(getLocationOnScreen(), getSize()).contains(mouseScreenLocation)) {
return;
@@ -17,10 +17,12 @@ package com.intellij.codeInsight.hint;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.ColoredSideBorder;
import com.intellij.ui.HintHint;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleColoredText;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
@@ -29,12 +31,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class HintUtil {
@@ -52,16 +50,17 @@ public class HintUtil {
}
public static JComponent createInformationLabel(@NotNull String text) {
return createInformationLabel(text, null, null);
return createInformationLabel(text, null, null, null);
}
public static JComponent createInformationLabel(@NotNull String text,
@Nullable HyperlinkListener hyperlinkListener,
@Nullable MouseListener mouseListener)
@Nullable MouseListener mouseListener,
@Nullable Ref<Consumer<String>> updatedTextConsumer)
{
HintHint hintHint = new HintHint().setTextBg(INFORMATION_COLOR).setTextFg(Color.black).setFont(getBoldFont()).setAwtTooltip(true);
HintLabel label = new HintLabel();
final HintLabel label = new HintLabel();
label.setText(text, hintHint);
label.setIcon(INFORMATION_ICON);
@@ -79,6 +78,14 @@ public class HintUtil {
if (mouseListener != null) {
label.myPane.addMouseListener(mouseListener);
}
if (updatedTextConsumer != null) {
updatedTextConsumer.set(new Consumer<String>() {
@Override
public void consume(String s) {
label.myPane.setText(s);
}
});
}
return label;
}
@@ -148,18 +155,6 @@ public class HintUtil {
return UIUtil.getLabelFont().deriveFont(Font.BOLD);
}
public static JLabel createAdComponent(final String bottomText) {
return createAdComponent(bottomText, getDefaultAdComponentBorder());
}
public static EmptyBorder getDefaultAdComponentBorder() {
return new EmptyBorder(1, 2, 1, 2);
}
public static JLabel createAdComponent(final String bottomText, final Border border) {
return createAdComponent(bottomText, border, SwingUtilities.LEFT);
}
public static JLabel createAdComponent(final String bottomText, final Border border, @JdkConstants.HorizontalAlignment int alignment) {
JLabel label = new JLabel();
label.setText(bottomText);
@@ -227,8 +222,8 @@ public class HintUtil {
remove(myIcon);
}
myIcon = new JLabel(icon, JLabel.CENTER);
myIcon.setVerticalAlignment(JLabel.TOP);
myIcon = new JLabel(icon, SwingConstants.CENTER);
myIcon.setVerticalAlignment(SwingConstants.TOP);
add(myIcon, BorderLayout.WEST);