PY-23247 Fixed: Shorten inferred type of zip function

Process overloads in PythonDocumentationProvider separately.
This commit is contained in:
Semyon Proshev
2017-09-22 15:52:17 +03:00
parent 9a3ec2f1d4
commit 8d877fbe29
12 changed files with 153 additions and 0 deletions
@@ -48,6 +48,7 @@ import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.pyi.PyiUtil;
import com.jetbrains.python.toolbox.ChainIterable;
import one.util.streamex.StreamEx;
import org.apache.commons.httpclient.HttpClient;
@@ -156,6 +157,9 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
@NotNull Function<String, String> escapedNameMapper,
@NotNull Function<String, String> escaper,
@NotNull TypeEvalContext context) {
final List<PyFunction> overloads = PyiUtil.getOverloads(function, context);
if (!overloads.isEmpty()) return describeOverload(function, overloads, escapedNameMapper, escaper, context);
final ChainIterable<String> result = new ChainIterable<>();
final String name = function.getName();
@@ -172,6 +176,33 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
return result;
}
@NotNull
private static ChainIterable<String> describeOverload(@NotNull PyFunction function,
@NotNull List<PyFunction> overloads,
@NotNull Function<String, String> escapedNameMapper,
@NotNull Function<String, String> escaper,
@NotNull TypeEvalContext context) {
final ChainIterable<String> result = new ChainIterable<>();
final String name = function.getName();
result
.addItem(escaper.apply("def "))
.addItem(escapedNameMapper.apply(escaper.apply(name)))
.addItem(escaper.apply("\nPossible types:\n"));
boolean first = true;
for (PyFunction overload : overloads) {
if (!first) {
result.addItem(escaper.apply("\n"));
}
result.addItem(escaper.apply("\u2022 "));
describeTypeWithLinks(context.getType(overload), context, function, result);
first = false;
}
return result;
}
@Nullable
private static String describeExpression(@NotNull PyExpression expression,
@NotNull PsiElement originalElement,
@@ -0,0 +1 @@
<html><body><code>def&nbsp;<b>foo</b><br>Possible&nbsp;types:<br>&nbsp;(param:&nbsp;<a href="psi_element://#typename#str">str</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#str">str</a><br>&nbsp;(param:&nbsp;<a href="psi_element://#typename#int">int</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a></code></body></html>
@@ -0,0 +1,15 @@
from typing import overload
@overload
def foo(param: str) -> str:
pass
@overload
def foo(param: int) -> int:
pass
def fo<the_ref>o(param: bool) -> bool:
pass
@@ -0,0 +1,5 @@
@typing.overload
def foo
Possible types:
• (p:&nbsp;<a href="psi_element://#typename#int">int</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a>
• (p:&nbsp;<a href="psi_element://#typename#str">str</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#str">str</a>
@@ -0,0 +1,14 @@
import typing
@typing.overload
def foo(p: int) -> int:
pass
@typing.overload
def foo(p: str) -> str:
pass
<the_ref>foo(1)
@@ -0,0 +1,4 @@
def foo
Possible types:
• (param:&nbsp;<a href="psi_element://#typename#str">str</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#str">str</a>
• (param:&nbsp;<a href="psi_element://#typename#int">int</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a>
@@ -0,0 +1,18 @@
from typing import overload
@overload
def foo(param: str) -> str:
pass
@overload
def foo(param: int) -> int:
pass
def foo(param: bool) -> bool:
pass
<the_ref>foo(1)
+1
View File
@@ -0,0 +1 @@
<html><body><code>@<i>typing.overload</i><br>def&nbsp;<b>foo</b><br>Possible&nbsp;types:<br>&nbsp;(p:&nbsp;<a href="psi_element://#typename#int">int</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a><br>&nbsp;(p:&nbsp;<a href="psi_element://#typename#str">str</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#str">str</a></code></body></html>
+14
View File
@@ -0,0 +1,14 @@
import typing
@typing.overload
def foo(p: int) -> int:
pass
@typing.overload
def foo(p: str) -> str:
pass
<the_ref>foo(1)
@@ -0,0 +1 @@
<html><body><code>def&nbsp;<b>foo</b><br>Possible&nbsp;types:<br>&nbsp;(param:&nbsp;<a href="psi_element://#typename#str">str</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#str">str</a><br>&nbsp;(param:&nbsp;<a href="psi_element://#typename#int">int</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a></code></body></html>
@@ -0,0 +1,18 @@
from typing import overload
@overload
def foo(param: str) -> str:
pass
@overload
def foo(param: int) -> int:
pass
def foo(param: bool) -> bool:
pass
<the_ref>foo(1)
@@ -351,4 +351,35 @@ public class PyQuickDocTest extends LightMarkedTestCase {
public void testHoverOverClassWithAllKindSuperClassExpressions() {
runWithLanguageLevel(LanguageLevel.PYTHON30, this::checkHover);
}
// PY-23247
public void testOverloads() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::checkHTMLOnly);
}
// PY-23247
public void testHoverOverOverloads() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::checkHover);
}
// PY-23247
public void testOverloadsAndImplementation() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::checkHTMLOnly);
}
// PY-23247
public void testHoverOverOverloadsAndImplementation() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::checkHover);
}
// PY-23247
public void testDocOnImplementationWithOverloads() {
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
final PsiElement originalElement = loadTest().get("<the_ref>");
checkByHTML(myProvider.generateDoc(originalElement.getParent(), originalElement));
}
);
}
}