provide effective external javadoc url (IDEA-126569)

This commit is contained in:
Anna Kozlova
2014-06-26 15:45:13 +02:00
parent c945ab88ab
commit d124016fd5
3 changed files with 151 additions and 103 deletions
@@ -40,6 +40,7 @@ import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
@@ -65,6 +66,7 @@ import javax.swing.event.HyperlinkListener;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Stack;
@@ -98,6 +100,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
private final JComponent mySettingsPanel;
private final MyShowSettingsButton myShowSettingsButton;
private boolean myIgnoreFontSizeSliderChange;
private String myEffectiveExternalUrl;
private static class Context {
final SmartPsiElementPointer element;
@@ -461,7 +464,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
myForwardStack.clear();
}
updateControlState();
setData(element, text, clearHistory);
setData(element, text, clearHistory, null);
if (clean) {
myIsEmpty = false;
}
@@ -480,7 +483,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
myBackStack.clear();
}
public void setData(PsiElement _element, String text, final boolean clearHistory) {
public void setData(PsiElement _element, String text, final boolean clearHistory, String effectiveExternalUrl) {
myEffectiveExternalUrl = effectiveExternalUrl;
if (myElement != null) {
myBackStack.push(saveContext());
myForwardStack.clear();
@@ -683,10 +687,16 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
}
if (!processed) {
final List<String> urls = provider.getUrlFor(element, originalElement);
assert urls != null : provider;
assert !urls.isEmpty() : provider;
ExternalJavaDocAction.showExternalJavadoc(urls);
final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext());
final List<String> urls;
if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) {
urls = Collections.singletonList(myEffectiveExternalUrl);
} else {
urls = provider.getUrlFor(element, originalElement);
assert urls != null : provider;
assert !urls.isEmpty() : provider;
}
ExternalJavaDocAction.showExternalJavadoc(urls, component);
}
}
}
@@ -615,99 +615,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
private DocumentationCollector getDefaultCollector(@NotNull final PsiElement element, @Nullable final PsiElement originalElement) {
return new DocumentationCollector() {
@Override
@Nullable
public String getDocumentation() throws Exception {
final DocumentationProvider provider = ApplicationManager.getApplication().runReadAction(
new Computable<DocumentationProvider>() {
@Override
public DocumentationProvider compute() {
return getProviderFromElement(element, originalElement);
}
}
);
if (myParameterInfoController != null) {
final String doc = ApplicationManager.getApplication().runReadAction(
new NullableComputable<String>() {
@Override
public String compute() {
return generateParameterInfoDocumentation(provider);
}
}
);
if (doc != null) return doc;
}
if (provider instanceof ExternalDocumentationProvider) {
final List<String> urls = ApplicationManager.getApplication().runReadAction(
new NullableComputable<List<String>>() {
@Override
public List<String> compute() {
final SmartPsiElementPointer originalElementPtr = element.getUserData(ORIGINAL_ELEMENT_KEY);
final PsiElement originalElement = originalElementPtr != null ? originalElementPtr.getElement() : null;
if (((ExternalDocumentationProvider)provider).hasDocumentationFor(element, originalElement)) {
return provider.getUrlFor(element, originalElement);
}
return null;
}
}
);
if (urls != null) {
final String doc = ((ExternalDocumentationProvider)provider).fetchExternalDocumentation(myProject, element, urls);
if (doc != null) return doc;
}
}
return ApplicationManager.getApplication().runReadAction(
new Computable<String>() {
@Override
@Nullable
public String compute() {
final SmartPsiElementPointer originalElement = element.getUserData(ORIGINAL_ELEMENT_KEY);
return provider.generateDoc(element, originalElement != null ? originalElement.getElement() : null);
}
}
);
}
@Nullable
private String generateParameterInfoDocumentation(DocumentationProvider provider) {
final Object[] objects = myParameterInfoController.getSelectedElements();
if (objects.length > 0) {
@NonNls StringBuffer sb = null;
for (Object o : objects) {
PsiElement parameter = null;
if (o instanceof PsiElement) {
parameter = (PsiElement)o;
}
if (parameter != null) {
final SmartPsiElementPointer originalElement = parameter.getUserData(ORIGINAL_ELEMENT_KEY);
final String str2 = provider.generateDoc(parameter, originalElement != null ? originalElement.getElement() : null);
if (str2 == null) continue;
if (sb == null) sb = new StringBuffer();
sb.append(str2);
sb.append("<br>");
}
else {
sb = null;
break;
}
}
if (sb != null) return sb.toString();
}
return null;
}
@Override
@Nullable
public PsiElement getElement() {
return element.isValid() ? element : null;
}
};
return new DefaultDocumentationCollector(element, originalElement);
}
@Nullable
@@ -813,7 +721,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
component.setText(component.getText(), element, true, clearHistory);
}
else {
component.setData(element, documentationText, clearHistory);
component.setData(element, documentationText, clearHistory, provider.getEffectiveExternalUrl());
}
final AbstractPopup jbPopup = (AbstractPopup)getDocInfoHint();
@@ -945,6 +853,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
public PsiElement getElement() {
return psiElement;
}
@Nullable
@Override
public String getEffectiveExternalUrl() {
return url;
}
}, component);
processed = true;
}
@@ -992,6 +906,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
return psiElement;
}
@Nullable
@Override
public String getEffectiveExternalUrl() {
return url;
}
}, component);
}
}
@@ -1062,5 +982,122 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
String getDocumentation() throws Exception;
@Nullable
PsiElement getElement();
@Nullable
String getEffectiveExternalUrl();
}
private class DefaultDocumentationCollector implements DocumentationCollector {
private final PsiElement myElement;
private final PsiElement myOriginalElement;
private String myEffectiveUrl;
public DefaultDocumentationCollector(PsiElement element, PsiElement originalElement) {
myElement = element;
myOriginalElement = originalElement;
}
@Override
@Nullable
public String getDocumentation() throws Exception {
final DocumentationProvider provider = ApplicationManager.getApplication().runReadAction(
new Computable<DocumentationProvider>() {
@Override
public DocumentationProvider compute() {
return getProviderFromElement(myElement, myOriginalElement);
}
}
);
if (myParameterInfoController != null) {
final String doc = ApplicationManager.getApplication().runReadAction(
new NullableComputable<String>() {
@Override
public String compute() {
return generateParameterInfoDocumentation(provider);
}
}
);
if (doc != null) return doc;
}
if (provider instanceof ExternalDocumentationProvider) {
final List<String> urls = ApplicationManager.getApplication().runReadAction(
new NullableComputable<List<String>>() {
@Override
public List<String> compute() {
final SmartPsiElementPointer originalElementPtr = myElement.getUserData(ORIGINAL_ELEMENT_KEY);
final PsiElement originalElement = originalElementPtr != null ? originalElementPtr.getElement() : null;
if (((ExternalDocumentationProvider)provider).hasDocumentationFor(myElement, originalElement)) {
return provider.getUrlFor(myElement, originalElement);
}
return null;
}
}
);
if (urls != null) {
for (String url : urls) {
final String doc = ((ExternalDocumentationProvider)provider).fetchExternalDocumentation(myProject, myElement, Collections.singletonList(url));
if (doc != null) {
myEffectiveUrl = url;
return doc;
}
}
}
}
return ApplicationManager.getApplication().runReadAction(
new Computable<String>() {
@Override
@Nullable
public String compute() {
final SmartPsiElementPointer originalElement = myElement.getUserData(ORIGINAL_ELEMENT_KEY);
return provider.generateDoc(myElement, originalElement != null ? originalElement.getElement() : null);
}
}
);
}
@Nullable
private String generateParameterInfoDocumentation(DocumentationProvider provider) {
final Object[] objects = myParameterInfoController.getSelectedElements();
if (objects.length > 0) {
@NonNls StringBuffer sb = null;
for (Object o : objects) {
PsiElement parameter = null;
if (o instanceof PsiElement) {
parameter = (PsiElement)o;
}
if (parameter != null) {
final SmartPsiElementPointer originalElement = parameter.getUserData(ORIGINAL_ELEMENT_KEY);
final String str2 = provider.generateDoc(parameter, originalElement != null ? originalElement.getElement() : null);
if (str2 == null) continue;
if (sb == null) sb = new StringBuffer();
sb.append(str2);
sb.append("<br>");
}
else {
sb = null;
break;
}
}
if (sb != null) return sb.toString();
}
return null;
}
@Override
@Nullable
public PsiElement getElement() {
return myElement.isValid() ? myElement : null;
}
@Nullable
@Override
public String getEffectiveExternalUrl() {
return myEffectiveUrl;
}
}
}
@@ -37,6 +37,7 @@ import com.intellij.psi.PsiReference;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.HashSet;
import java.util.List;
@@ -79,7 +80,7 @@ public class ExternalJavaDocAction extends AnAction {
final List<String> urls = provider.getUrlFor(element, originalElement);
if (urls != null && !urls.isEmpty()) {
showExternalJavadoc(urls);
showExternalJavadoc(urls, PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext));
}
else if (provider instanceof ExternalDocumentationProvider) {
final ExternalDocumentationProvider externalDocumentationProvider = (ExternalDocumentationProvider)provider;
@@ -89,7 +90,7 @@ public class ExternalJavaDocAction extends AnAction {
}
}
public static void showExternalJavadoc(List<String> urls) {
public static void showExternalJavadoc(List<String> urls, Component component) {
final HashSet<String> set = new HashSet<String>(urls);
if (set.size() > 1) {
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>("Choose external documentation root", ArrayUtil.toStringArray(set)) {
@@ -98,7 +99,7 @@ public class ExternalJavaDocAction extends AnAction {
BrowserUtil.browse(selectedValue);
return FINAL_CHOICE;
}
}).showInBestPositionFor(DataManager.getInstance().getDataContext());
}).showInBestPositionFor(DataManager.getInstance().getDataContext(component));
}
else if (set.size() == 1) {
BrowserUtil.browse(urls.get(0));