From 262f51fd53e0f9db6b5275ef38488a80a0029142 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 29 Jul 2013 19:00:30 +0400 Subject: [PATCH 1/2] Use the type of the original element for Ctrl-Hover info (PY-10386) --- .../PythonDocumentationProvider.java | 16 +++++++++------- .../quickdoc/HoverOverControlFlowUnion.html | 2 ++ .../quickdoc/HoverOverControlFlowUnion.py | 6 ++++++ .../com/jetbrains/python/PyQuickDocTest.java | 4 ++++ 4 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 python/testData/quickdoc/HoverOverControlFlowUnion.html create mode 100644 python/testData/quickdoc/HoverOverControlFlowUnion.py diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java index 2e6d4058ff76..6ee637fe6f10 100644 --- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java +++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java @@ -100,8 +100,8 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i return describeDecorators(cls, LSame2, ", ", LSame1).add(describeClass(cls, LSame2, false, false)).toString() + "\n" + summary; } - else if (element instanceof PyTargetExpression || element instanceof PyNamedParameter) { - return describeExpression((PyExpression)element); + else if (element instanceof PyExpression) { + return describeExpression((PyExpression)element, originalElement); } return null; } @@ -131,7 +131,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i } @Nullable - private static String describeExpression(PyExpression expr) { + private static String describeExpression(@NotNull PyExpression expr, @NotNull PsiElement originalElement) { final String name = expr.getName(); if (name != null) { StringBuilder result = new StringBuilder((expr instanceof PyNamedParameter) ? "parameter" : "variable"); @@ -143,15 +143,17 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i result.append(String.format(" \"%s\"", function.getName())); } } - result.append("\n").append(describeExpressionType(expr)); + if (originalElement instanceof PyTypedElement) { + result.append("\n").append(describeType((PyTypedElement)originalElement)); + } return result.toString(); } return null; } - static String describeExpressionType(PyExpression expr) { - final TypeEvalContext context = TypeEvalContext.userInitiated(expr.getContainingFile()); - return String.format("Inferred type: %s", getTypeName(context.getType(expr), context)); + static String describeType(@NotNull PyTypedElement element) { + final TypeEvalContext context = TypeEvalContext.userInitiated(element.getContainingFile()); + return String.format("Inferred type: %s", getTypeName(context.getType(element), context)); } public static String getTypeDescription(@NotNull PyFunction fun) { diff --git a/python/testData/quickdoc/HoverOverControlFlowUnion.html b/python/testData/quickdoc/HoverOverControlFlowUnion.html new file mode 100644 index 000000000000..056d6ba8ce3c --- /dev/null +++ b/python/testData/quickdoc/HoverOverControlFlowUnion.html @@ -0,0 +1,2 @@ +variable "x" +Inferred type: one of (str, int) diff --git a/python/testData/quickdoc/HoverOverControlFlowUnion.py b/python/testData/quickdoc/HoverOverControlFlowUnion.py new file mode 100644 index 000000000000..74ceb505df1b --- /dev/null +++ b/python/testData/quickdoc/HoverOverControlFlowUnion.py @@ -0,0 +1,6 @@ +def foo(c): + if c: + x = 'foo' + else: + x = 1 + return x \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java index 5227fc4c0521..de9ea7ff9c04 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickDocTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickDocTest.java @@ -216,4 +216,8 @@ public class PyQuickDocTest extends LightMarkedTestCase { public void testHoverOverParameter() { checkHover(); } + + public void testHoverOverControlFlowUnion() { + checkHover(); + } } From 03a4da2204888ef28cae226be9c6c39a99388c2a Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 29 Jul 2013 19:23:49 +0400 Subject: [PATCH 2/2] Fallback to arrow return type only after structured docstring formats (PY-9849) --- .../python/psi/impl/PyFunctionImpl.java | 31 ++++++++++--------- .../com/jetbrains/python/PyTypeTest.java | 11 +++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 378ab8a676cc..c61693c075d7 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -400,23 +400,26 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp @Nullable private String extractReturnType() { + final String ARROW = "->"; + final StructuredDocString structuredDocString = getStructuredDocString(); + if (structuredDocString != null) { + return structuredDocString.getReturnType(); + } final String docString = getDocStringValue(); - if (docString == null) { - return null; - } - final List lines = StringUtil.split(docString, "\n"); - while (lines.size() > 0 && lines.get(0).trim().length() == 0) { - lines.remove(0); - } - if (lines.size() > 1 && lines.get(1).trim().length() == 0) { - String firstLine = lines.get(0); - int pos = firstLine.lastIndexOf("->"); - if (pos >= 0) { - return firstLine.substring(pos + 2).trim(); + if (docString != null && docString.contains(ARROW)) { + final List lines = StringUtil.split(docString, "\n"); + while (lines.size() > 0 && lines.get(0).trim().length() == 0) { + lines.remove(0); + } + if (lines.size() > 1 && lines.get(1).trim().length() == 0) { + String firstLine = lines.get(0); + int pos = firstLine.lastIndexOf(ARROW); + if (pos >= 0) { + return firstLine.substring(pos + 2).trim(); + } } } - final StructuredDocString structuredDocString = getStructuredDocString(); - return structuredDocString != null ? structuredDocString.getReturnType() : null; + return null; } private static class ReturnVisitor extends PyRecursiveElementVisitor { diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index 3daeb4fd9c57..2348a1039500 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -629,6 +629,17 @@ public class PyTypeTest extends PyTestCase { assertTrue(PyTypeChecker.isUnknown(type)); } + public void testParameterOfFunctionTypeAndReturnValue() { + doTest("int", + "def func(f):\n" + + " '''\n" + + " :type f: (unknown) -> str\n" + + " '''\n" + + " return 1\n" + + "\n" + + "expr = func(foo)\n"); + } + private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) { return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing(); }