diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index fd61de48cc49..a4419c65a061 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -785,6 +785,7 @@ + diff --git a/python/src/com/jetbrains/numpy/codeInsight/SciPyDocumentationLinkProvider.kt b/python/src/com/jetbrains/numpy/codeInsight/SciPyDocumentationLinkProvider.kt new file mode 100644 index 000000000000..efe1f22759eb --- /dev/null +++ b/python/src/com/jetbrains/numpy/codeInsight/SciPyDocumentationLinkProvider.kt @@ -0,0 +1,53 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.jetbrains.numpy.codeInsight + +import com.google.common.collect.ImmutableMap +import com.intellij.psi.PsiElement +import com.jetbrains.python.documentation.PythonDocumentationLinkProvider +import com.jetbrains.python.documentation.PythonDocumentationProvider +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader + + +class SciPyDocumentationLinkProvider : PythonDocumentationLinkProvider { + + private val nameToWebpageName: Map by lazy { + val b = ImmutableMap.builder() + try { + BufferedReader( + InputStreamReader( + SciPyDocumentationLinkProvider::class.java + .getResourceAsStream("/com/jetbrains/numpy/codeInsight/scipyNameMapping.tsv"), // generated by scipy_doc_mapping.py + Charsets.UTF_8 + ) + ).use { inputStream -> + inputStream.lines().forEach { line -> + val kv = line.split("\t".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + b.put(kv[0], kv[1]) + } + } + } + catch (e: IOException) { + throw RuntimeException(e) + } + + b.build() + } + + override fun getExternalDocumentationUrl(element: PsiElement?, originalElement: PsiElement?): String? { + val qname = PythonDocumentationProvider.getFullQualifiedName(element) + + return if (qname != null && qname.firstComponent in listOf("numpy", "scipy")) { + val webPage = nameToWebpageName.get(qname.toString()) + if (webPage != null) { + "https://docs.scipy.org/doc/${qname.firstComponent}/reference/generated/$webPage.html" + } else { + "https://docs.scipy.org/doc/${qname.firstComponent}/reference/" + } + } + else null + + } + +} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/documentation/scipyNameMapping.tsv b/python/src/com/jetbrains/numpy/codeInsight/scipyNameMapping.tsv similarity index 100% rename from python/src/com/jetbrains/python/documentation/scipyNameMapping.tsv rename to python/src/com/jetbrains/numpy/codeInsight/scipyNameMapping.tsv diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationMap.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationMap.java index a658035761f9..9ab22848cb6b 100644 --- a/python/src/com/jetbrains/python/documentation/PythonDocumentationMap.java +++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationMap.java @@ -2,7 +2,7 @@ package com.jetbrains.python.documentation; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; @@ -17,17 +17,11 @@ import com.jetbrains.python.psi.PyFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * @author yole @@ -46,28 +40,6 @@ public class PythonDocumentationMap implements PersistentStateComponent nameToWebpageName = ((Supplier>)() -> { - final ImmutableMap.Builder b = ImmutableMap.builder(); - try (final BufferedReader inputStream = new BufferedReader( - new InputStreamReader( - ScipyExternalDocumentationMap.class - .getResourceAsStream("/com/jetbrains/python/documentation/scipyNameMapping.tsv"), - StandardCharsets.US_ASCII - ) - )) { - inputStream.lines().forEach(line -> { - final String[] kv = line.split("\t"); - b.put(kv[0], kv[1]); - }); - } - catch (final IOException e) { - throw new RuntimeException(e); - } - return b.build(); - }).get(); - } - public static class Entry { private String myPrefix; private String myUrlPattern; @@ -124,10 +96,9 @@ public class PythonDocumentationMap implements PersistentStateComponent strings = Lists.newArrayList("django", "numpy", "scipy"); + // those packages are handled by implementations of PythonDocumentationLinkProvider + state.setEntries(state.getEntries().stream().filter((entry -> !strings.contains(entry.myPrefix))).collect(Collectors.toList())); } private static void addAbsentEntriesFromDefaultState(@NotNull State state) { State defaultState = new State(); - for (Entry e: defaultState.myEntries) { + for (Entry e : defaultState.myEntries) { if (state.myEntries.stream().noneMatch(entry -> entry.myPrefix.equals(e.myPrefix))) { state.addEntry(e.getPrefix(), e.getUrlPattern()); } @@ -239,10 +217,6 @@ public class PythonDocumentationMap implements PersistentStateComponentile) """.trimIndent(), """
""".trimIndent()) } + fun testNumpyNdarray() { + myFixture.copyDirectoryToProject("/inspections/PyNumpyType/numpy", "numpy") + + doTestDocumentationUrl("""import numpy + a = numpy.multiarray.ndarray() + """.trimMargin(), "https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html", myFixture) + } + }