From 552e73b80f510f03d7ef4303744e7d68f8ba88e0 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 22 Sep 2015 14:47:04 +0300 Subject: [PATCH] PY-16987 Google and Numpy docstrings return null as parameter type if it wasn't specified in the docstring Previously their parsers returned empty string in this case, and it wasn't possible to easily tell whether parameter is omitted from the docstring completely or it's just its type wasn't written. --- .../python/psi/StructuredDocString.java | 15 +++++- .../docstrings/DocStringUtil.java | 2 +- .../docstrings/SectionBasedDocString.java | 13 ++--- .../com/jetbrains/python/Py3TypeTest.java | 51 +++++++++++++++++++ 4 files changed, 70 insertions(+), 11 deletions(-) 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);