diff --git a/python/openapi/intellij.python.community.iml b/python/openapi/intellij.python.community.iml
index 98ec21c89d51..e111859d7cc8 100644
--- a/python/openapi/intellij.python.community.iml
+++ b/python/openapi/intellij.python.community.iml
@@ -12,5 +12,6 @@
+
\ No newline at end of file
diff --git a/python/openapi/src/com/jetbrains/python/documentation/PythonDocumentationLinkProvider.java b/python/openapi/src/com/jetbrains/python/documentation/PythonDocumentationLinkProvider.java
index ee49e67b2af6..f4fb137eddc8 100644
--- a/python/openapi/src/com/jetbrains/python/documentation/PythonDocumentationLinkProvider.java
+++ b/python/openapi/src/com/jetbrains/python/documentation/PythonDocumentationLinkProvider.java
@@ -18,7 +18,11 @@ package com.jetbrains.python.documentation;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
import org.jetbrains.annotations.Nullable;
+import org.jsoup.nodes.Document;
+
+import java.util.function.Function;
/**
* @author yole
@@ -39,4 +43,9 @@ public interface PythonDocumentationLinkProvider {
default String getExternalDocumentationRoot(Sdk sdk) {
return "";
}
+
+ @Nullable
+ default Function quickDocExtractor(PsiNamedElement namedElement) {
+ return null;
+ }
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
index 3932849e7e16..c84b6afefb73 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
@@ -17,7 +17,6 @@ package com.jetbrains.python.codeInsight.stdlib;
import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
@@ -32,8 +31,12 @@ import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.sdk.PythonSdkType;
+import org.jetbrains.annotations.Nullable;
+import org.jsoup.nodes.Document;
+import org.jsoup.select.Elements;
import java.util.Map;
+import java.util.function.Function;
/**
* @author yole
@@ -984,15 +987,35 @@ public class PyStdlibDocumentationLinkProvider implements PythonDocumentationLin
return urlBuilder.toString();
}
+ @Nullable
+ @Override
+ public Function quickDocExtractor(PsiNamedElement namedElement) {
+ return (Function)document -> {
+ final String moduleName = getModuleNameForDocumentationUrl(namedElement, namedElement);
+
+ final String elementId = namedElement != null ? moduleName + "." + namedElement.getName() : "module-" + moduleName;
+ document.select("a.headerlink").remove();
+ final Elements parents = document.getElementsByAttributeValue("id", elementId).parents();
+ if (parents.isEmpty()) {
+ final Elements moduleElement = document.getElementsByAttributeValue("id", "module-" + moduleName);
+ if (moduleElement != null) {
+ return moduleElement.toString();
+ }
+ return document.toString();
+ }
+ return parents.get(0).toString();
+ };
+ }
+
private String getStdlibUrlFor(PsiElement element, QualifiedName moduleName, Sdk sdk) {
StringBuilder urlBuilder = new StringBuilder(getExternalDocumentationRoot(sdk));
- Pair modName = getModuleName(moduleName.toString());
+ String modName = getModuleName(moduleName.toString());
final String pyVersion = PythonDocumentationProvider.pyVersion(sdk.getVersionString());
final Map moduleToWebpageName =
pyVersion != null && pyVersion.startsWith("3") ? py3LibraryModulesToWebpageName : py2LibraryModulesToWebpageName;
- final String webpageName = moduleToWebpageName.get(modName.first);
+ final String webpageName = moduleToWebpageName.get(modName);
final boolean isBuiltin = "__builtin__".equals(webpageName) || "builtins".equals(webpageName);
final String className = element instanceof PyFunction && ((PyFunction)element).getContainingClass() != null ?
@@ -1009,20 +1032,18 @@ public class PyStdlibDocumentationLinkProvider implements PythonDocumentationLin
if (webpageName2 != null && element instanceof PsiNamedElement && !(element instanceof PyFile)) {
urlBuilder.append('#');
if (!isBuiltin) {
- urlBuilder.append(modName.second).append(".");
+ urlBuilder.append(modName).append(".");
}
urlBuilder.append(qName);
}
return urlBuilder.toString();
}
- private static Pair getModuleName(String qname) {
- String moduleName = qname;
+ private static String getModuleName(String qname) {
if (qname.equals("ntpath") || qname.equals("posixpath")) {
qname = "os.path";
} else if (qname.equals("genericpath")) {
qname = "os.path";
- moduleName = qname;
}
else if (qname.equals("nt")) {
qname = "os";
@@ -1034,13 +1055,13 @@ public class PyStdlibDocumentationLinkProvider implements PythonDocumentationLin
qname = "xml.parsers.expat";
}
- return Pair.create(qname, moduleName);
+ return qname;
}
public String getModuleNameForDocumentationUrl(PsiElement element, PsiElement originalElement) {
QualifiedName qName = QualifiedNameFinder.findCanonicalImportPath(element, originalElement);
- return qName != null? getModuleName(qName.toString()).second : "";
+ return qName != null? getModuleName(qName.toString()) : "";
}
private static final class MyBuilder extends ImmutableMap.Builder {
diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
index 99a180014763..b7822df19936 100644
--- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
+++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
@@ -631,43 +631,28 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
namedElement = containingClass;
}
}
- final PyStdlibDocumentationLinkProvider stdlibDocumentationLinkProvider =
- PythonDocumentationLinkProvider.EP_NAME.findExtensionOrFail(PyStdlibDocumentationLinkProvider.class);
+ for (final PythonDocumentationLinkProvider documentationLinkProvider :
+ PythonDocumentationLinkProvider.EP_NAME.getExtensionList()) {
- String url = null;
+ Function quickDocExtractor = documentationLinkProvider.quickDocExtractor(namedElement);
- if (docUrls.size()>0) {
- url = docUrls.get(0);
- } else {
- url = stdlibDocumentationLinkProvider.getExternalDocumentationUrl(element, element);
- }
-
- if (url == null) {
- return null;
- }
-
- final String moduleName = stdlibDocumentationLinkProvider.getModuleNameForDocumentationUrl(element, element);
-
- try {
- final Document document = Jsoup.parse(new URL(url), 1000);
- final String elementId = namedElement != null ? moduleName + "." + namedElement.getName() : "module-" + moduleName;
- document.select("a.headerlink").remove();
- final Elements parents = document.getElementsByAttributeValue("id", elementId).parents();
- if (parents.isEmpty()) {
- final Elements moduleElement = document.getElementsByAttributeValue("id", "module-" + moduleName);
- if (moduleElement != null) {
- return moduleElement.toString();
+ if (quickDocExtractor != null) {
+ for (String url : docUrls) {
+ try {
+ final Document document = Jsoup.parse(new URL(url), 1000);
+ String quickDoc = quickDocExtractor.apply(document);
+ if (StringUtil.isNotEmpty(quickDoc)) {
+ return quickDoc;
+ }
+ }
+ catch (IOException e) {
+ }
}
- return document.toString();
}
- return parents.get(0).toString();
- }
- catch (MalformedURLException ignored) {
- }
- catch (IOException ignored) {
}
+
return null;
});
}