PY-9795 Better removal of multiple parameters in various kinds of docstrings
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Thu, 27 Aug 2015 14:05:17 +0000 (17:05 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Wed, 2 Sep 2015 11:35:28 +0000 (14:35 +0300)
In particular, if several parameters were deleted via Change Signature
refactoring.

python/src/com/jetbrains/python/documentation/DocStringUtil.java
python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java
python/src/com/jetbrains/python/inspections/quickfix/PyRemoveParameterQuickFix.java
python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java
python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.after.py [new file with mode: 0644]
python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.before.py [new file with mode: 0644]
python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.after.py [new file with mode: 0644]
python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.before.py [new file with mode: 0644]
python/testSrc/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureTest.java

index 692f124038fa86209de01a6d024688663051d558..e340160f5bbc35bed3b971b19642e3fc6f9597ad 100644 (file)
@@ -41,6 +41,8 @@ import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.regex.Matcher;
 
@@ -266,8 +268,9 @@ public class DocStringUtil {
     final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(getModuleForElement(anchor));
     return settings.getFormatForFile(anchor.getContainingFile());
   }
-
-  public static void removeParamFromDocString(@NotNull PyStringLiteralExpression docString, @NotNull String paramName) {
+  
+  public static PyStringLiteralExpression removeParamsFromDocString(@NotNull PyStringLiteralExpression docString, 
+                                                                    @NotNull Collection<String> paramNames) {
     final Module module = getModuleForElement(docString);
     final DocStringFormat format = PyDocumentationSettings.getInstance(module).getFormatForFile(docString.getContainingFile());
     DocStringUpdater updater;
@@ -289,11 +292,20 @@ public class DocStringUtil {
         updater = new NumpyDocStringUpdater(numpyParsed, PyIndentUtil.getElementIndent(docString));
         break;
       default:
-        return;
+        return docString;
+    }
+    for (String name : paramNames) {
+      updater.removeParameter(name);
     }
-    updater.removeParameter(paramName);
     final String newText = updater.getDocStringText();
     final PyExpressionStatement replacement = PyElementGenerator.getInstance(docString.getProject()).createDocstring(newText);
-    docString.replace(replacement.getExpression());
+    return (PyStringLiteralExpression)docString.replace(replacement.getExpression());
+    
+  }
+
+  @NotNull
+  public static PyStringLiteralExpression removeParamsFromDocString(@NotNull PyStringLiteralExpression docString, 
+                                                                    @NotNull String... paramNames) {
+    return removeParamsFromDocString(docString, Arrays.asList(paramNames));
   }
 }
index 40ffa24033af6862f7f2abcbb8926d69356682b2..0bdd733da3a24d98feaa82f18ac887ec24e77183 100644 (file)
@@ -93,7 +93,7 @@ public class DocstringQuickFix implements LocalQuickFix {
         new PyDocstringGenerator(docStringOwner).withParam(myMissingText).buildAndInsert();
       }
       else if (myUnexpected != null) {
-        DocStringUtil.removeParamFromDocString(docStringExpression, myUnexpected);
+        DocStringUtil.removeParamsFromDocString(docStringExpression, myUnexpected);
       }
     }
   }
index 663d6a457e8346e541856f7c58978af33c67601b..bc41e03378db4a1d1ac0e5c6d9104a41c615a665 100644 (file)
@@ -73,7 +73,7 @@ public class PyRemoveParameterQuickFix implements LocalQuickFix {
       final PyStringLiteralExpression expression = pyFunction.getDocStringExpression();
       final String paramName = ((PyParameter)element).getName();
       if (expression != null && paramName != null) {
-        DocStringUtil.removeParamFromDocString(expression, paramName);
+        DocStringUtil.removeParamsFromDocString(expression, paramName);
       }
     }
 
index d108f416801f9c12e7b102e4b4edbb36f58e5bf6..31b157373b15ed55c795b5366bc728941e59a1e2 100644 (file)
@@ -327,7 +327,7 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
   }
 
   private static void fixDoc(PyChangeInfo changeInfo, @NotNull PyFunction function) {
-    final PyStringLiteralExpression docStringExpression = function.getDocStringExpression();
+    PyStringLiteralExpression docStringExpression = function.getDocStringExpression();
     if (docStringExpression == null) return;
     final PyParameterInfo[] parameters = changeInfo.getNewParameters();
     Set<String> names = new HashSet<String>();
@@ -336,12 +336,14 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
     }
     final Module module = ModuleUtilCore.findModuleForPsiElement(function);
     if (module == null) return;
+    final List<String> removedParamNames = new ArrayList<String>();
     for (PyParameter p : function.getParameterList().getParameters()) {
       final String paramName = p.getName();
       if (!names.contains(paramName) && paramName != null) {
-        DocStringUtil.removeParamFromDocString(docStringExpression, paramName);
+        removedParamNames.add(paramName);
       }
     }
+    DocStringUtil.removeParamsFromDocString(docStringExpression, removedParamNames);
   }
 
   private static void updateParameterList(PyChangeInfo changeInfo, PyFunction baseMethod) {
diff --git a/python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.after.py b/python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.after.py
new file mode 100644 (file)
index 0000000..d4424e0
--- /dev/null
@@ -0,0 +1,6 @@
+def f(a, d):
+    """
+    Params:
+      a : foo
+      d : quux
+    """
\ No newline at end of file
diff --git a/python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.before.py b/python/testData/refactoring/changeSignature/fixGoogleDocStringRemoveMultiple.before.py
new file mode 100644 (file)
index 0000000..27d642d
--- /dev/null
@@ -0,0 +1,8 @@
+def f(a, b, c, d):
+    """
+    Params:
+      a : foo
+      b : bar
+      c : baz
+      d : quux
+    """
\ No newline at end of file
diff --git a/python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.after.py b/python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.after.py
new file mode 100644 (file)
index 0000000..d77d0ce
--- /dev/null
@@ -0,0 +1,6 @@
+def f(a, d):
+    """
+    :param a : foo
+
+    :param d : quux
+    """
\ No newline at end of file
diff --git a/python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.before.py b/python/testData/refactoring/changeSignature/fixSphinxDocStringRemoveMultiple.before.py
new file mode 100644 (file)
index 0000000..e772c58
--- /dev/null
@@ -0,0 +1,10 @@
+def f(a, b, c, d):
+    """
+    :param a : foo
+    :param b : bar
+      another line of description
+
+    :type b: str
+    :param c : baz
+    :param d : quux
+    """
\ No newline at end of file
index d4b249ce0f514212520c3c0ac99582474d4d4b43..e178ddac72b42011bf0c19ac1b57db665d596e44 100644 (file)
@@ -23,6 +23,7 @@ import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 import com.jetbrains.python.PyBundle;
 import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.documentation.DocStringFormat;
 import com.jetbrains.python.fixtures.PyTestCase;
 import com.jetbrains.python.psi.LanguageLevel;
 import com.jetbrains.python.psi.PyFunction;
@@ -105,6 +106,26 @@ public class PyChangeSignatureTest extends PyTestCase {
     doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "a", null, false)));
   }
 
+  // PY-9795
+  public void testFixGoogleDocStringRemoveMultiple() {
+    runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {
+      public void run() {
+        doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "a", null, false), 
+                                                  new PyParameterInfo(3, "d", null, false)));
+      }
+    });
+  }
+
+  public void testFixSphinxDocStringRemoveMultiple() {
+    runWithDocStringFormat(DocStringFormat.REST, new Runnable() {
+      @Override
+      public void run() {
+        doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "a", null, false),
+                                                  new PyParameterInfo(3, "d", null, false)));
+      }
+    });
+  }
+
   public void testClassMethod() {
     doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "self", null, false), new PyParameterInfo(1, "a", null, true),
                                               new PyParameterInfo(-1, "b", "2", false)));