diff --git a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java index 748fd22de426..3e701cec9900 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java +++ b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java @@ -40,12 +40,16 @@ public interface StructuredDocString { /** * @param paramName {@code null} can be used for unnamed parameters descriptors, e.g. in docstring following class attribute + * @return {@code null} if specified parameter was omitted in the docstring completely, empty string if there was place for its type, + * but it was unfilled and trimmed type text otherwise. */ @Nullable String getParamType(@Nullable String paramName); /** * @param paramName {@code null} can be used for unnamed parameters descriptors, e.g. in docstring following class attribute + * @return {@code null} if specified parameter was omitted in the docstring completely, empty substring if there was place for its type, + * but it was unfilled and trimmed type substring otherwise. */ @Nullable Substring getParamTypeSubstring(@Nullable String paramName); @@ -68,9 +72,18 @@ public interface StructuredDocString { // getKeywordArgumentTypeString(name) @Nullable String getKeywordArgumentDescription(@Nullable String paramName); + + /** + * @return {@code null} if return type was omitted in the docstring completely, empty string if there was place for its type, + * but it was unfilled and trimmed type text otherwise. + */ @Nullable String getReturnType(); - @Nullable + + /** + * @return {@code null} if return type was omitted in the docstring completely, empty substring if there was place for its type, + * but it was unfilled and trimmed type substring otherwise. + */ @Nullable Substring getReturnTypeSubstring(); @Nullable diff --git a/python/src/com/jetbrains/python/documentation/docstrings/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/docstrings/DocStringUtil.java index 585d1d545a87..bc4ef7068b8f 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/DocStringUtil.java @@ -58,7 +58,7 @@ public class DocStringUtil { * @return structured docstring for one of supported formats or instance of {@link PlainDocString} if none was recognized. * @see #parse(String, PsiElement) */ - @Nullable + @NotNull public static StructuredDocString parse(@NotNull String text) { return parse(text, null); } diff --git a/python/src/com/jetbrains/python/documentation/docstrings/SectionBasedDocString.java b/python/src/com/jetbrains/python/documentation/docstrings/SectionBasedDocString.java index d0ba1cccbe74..8b4743313b97 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/SectionBasedDocString.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/SectionBasedDocString.java @@ -318,13 +318,8 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen @Nullable @Override public String getParamType(@Nullable String paramName) { - if (paramName != null) { - final SectionField field = getFirstFieldForParameter(paramName); - if (field != null) { - return field.getType(); - } - } - return null; + final Substring sub = getParamTypeSubstring(paramName); + return sub != null ? sub.toString() : null; } @Nullable @@ -429,8 +424,8 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen @Nullable @Override public String getReturnType() { - final SectionField field = getFirstReturnField(); - return field != null ? field.getType() : null; + final Substring sub = getReturnTypeSubstring(); + return sub != null ? sub.toString() : null; } @Nullable diff --git a/python/testSrc/com/jetbrains/python/Py3TypeTest.java b/python/testSrc/com/jetbrains/python/Py3TypeTest.java index a53df7457cbc..aa8b4ff764ae 100644 --- a/python/testSrc/com/jetbrains/python/Py3TypeTest.java +++ b/python/testSrc/com/jetbrains/python/Py3TypeTest.java @@ -115,6 +115,57 @@ public class Py3TypeTest extends PyTestCase { } }); } + + // PY-16987 + public void testNoTypeInGoogleDocstringParamAnnotation() { + runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() { + @Override + public void run() { + doTest("int", "def f(x: int):\n" + + " \"\"\"\n" + + " Args:\n" + + " x: foo\n" + + " \"\"\" \n" + + " expr = x"); + } + }); + } + + // PY-16987 + public void testUnfilledTypeInGoogleDocstringParamAnnotation() { + runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() { + @Override + public void run() { + doTest("Any", "def f(x: int):\n" + + " \"\"\"\n" + + " Args:\n" + + " x (): foo\n" + + " \"\"\" \n" + + " expr = x"); + } + }); + } + + // TODO: Same test for Numpy docstrings doesn't pass because typing provider is invoked earlier than NumpyDocStringTypeProvider + + // PY-16987 + public void testNoTypeInNumpyDocstringParamAnnotation() { + runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() { + @Override + public void run() { + doTest("int", "def f(x: int):\n" + + " \"\"\"\n" + + " Parameters\n" + + " ----------\n" + + " x\n" + + " foo\n" + + " \"\"\" \n" + + " expr = x"); + } + }); + } + + private void doTest(final String expectedType, final String text) { myFixture.configureByText(PythonFileType.INSTANCE, text);