PY-17635 Complete parameter names in ":type" declaration of reST docstrings
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Fri, 13 Nov 2015 16:04:37 +0000 (19:04 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Mon, 16 Nov 2015 11:32:04 +0000 (14:32 +0300)
python/src/com/jetbrains/python/codeInsight/completion/PyDocstringCompletionContributor.java
python/testData/completion/paramNameInTypeDeclarationInRestDocstring.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/PythonCompletionTest.java

index d5d386a622ad7f12b3cedf3eb39a0e66e37629c6..f18e7debb496da3cdebbcb2c4997c384a57f7364 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiNamedElement;
 import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ProcessingContext;
 import com.jetbrains.python.documentation.docstrings.DocStringParameterReference;
@@ -78,7 +79,19 @@ public class PyDocstringCompletionContributor extends CompletionContributor {
           }
         }
       }
-      else if (reference instanceof DocStringParameterReference) {
+      // For reST declaration like ":param foo: int" "foo" is PsiMultiReference that combines DocStringParameterReference and DocStringTypeReference
+      else if (reference instanceof PsiMultiReference) {
+        for (PsiReference innerReference : ((PsiMultiReference)reference).getReferences()) {
+          addVariantsFromDocstringReference(innerReference, result);
+        }
+      }
+      else {
+        addVariantsFromDocstringReference(reference, result);
+      }
+    }
+
+    private static void addVariantsFromDocstringReference(@NotNull PsiReference reference, @NotNull CompletionResultSet result) {
+      if (reference instanceof DocStringParameterReference) {
         for (PyNamedParameter param : ((DocStringParameterReference)reference).collectParameterVariants()) {
           result.addElement(LookupElementBuilder.createWithIcon(param));
         }
diff --git a/python/testData/completion/paramNameInTypeDeclarationInRestDocstring.py b/python/testData/completion/paramNameInTypeDeclarationInRestDocstring.py
new file mode 100644 (file)
index 0000000..0f53d53
--- /dev/null
@@ -0,0 +1,4 @@
+def f(foo, bar):
+    """
+    :type f<caret>
+    """
\ No newline at end of file
index 57494571cd094a1a40463e6d887c0ca96b2d8451..17d933cc9e06f33c7a2654fc4a80346e15b9dd17 100644 (file)
@@ -509,6 +509,18 @@ public class PythonCompletionTest extends PyTestCase {
     });
   }
 
+  // PY-17635
+  public void testParamNameInTypeDeclarationInRestDocstring() {
+    runWithDocStringFormat(DocStringFormat.REST, new Runnable() {
+      @Override
+      public void run() {
+        final List<String> variants = doTestByFile();
+        assertNotNull(variants);
+        assertContainsElements(variants, "foo");
+      }
+    });
+  }
+
   public void testPep328Completion() {  // PY-3409
     myFixture.copyDirectoryToProject("pep328", "pep328");
     myFixture.configureByFile("pep328/package/subpackage1/moduleX.py");