PY-16987 Google and Numpy docstrings return null as parameter type if it wasn't speci...
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Tue, 22 Sep 2015 11:47:04 +0000 (14:47 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Tue, 22 Sep 2015 15:44:08 +0000 (18:44 +0300)
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-api/src/com/jetbrains/python/psi/StructuredDocString.java
python/src/com/jetbrains/python/documentation/docstrings/DocStringUtil.java
python/src/com/jetbrains/python/documentation/docstrings/SectionBasedDocString.java
python/testSrc/com/jetbrains/python/Py3TypeTest.java

index 748fd22de426a9203fe7478dbece06aad88504b6..3e701cec9900beb4dac35a93d011f7b57fa2addb 100644 (file)
@@ -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
index 585d1d545a877e06bac7990470fdfa0e0014210f..bc4ef7068b8feed20faa0eaa6cfd40229edeed59 100644 (file)
@@ -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);
   }
index d0ba1cccbe74f1139f47bb78e7e707745a80a9c1..8b4743313b97a63cf10a737fe4796a2b3124b89c 100644 (file)
@@ -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
index a53df7457cbc492e6c9a06e6d0f555fa3c77998c..aa8b4ff764ae04f03d13461c9b78c63afaffb2d9 100644 (file)
@@ -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);