From 3e33798ac99113ae7e4564a0bfc2aa7b823cb966 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 23 Nov 2012 16:50:38 +0400 Subject: [PATCH] fixed docstring update while change signature --- .../python/editor/PythonDocCommentUtil.java | 35 +++++++++++++++++ .../quickfix/DocstringQuickFix.java | 38 +------------------ .../PyChangeSignatureUsageProcessor.java | 36 +++++++++++++++++- .../fixDocstringRemove.after.py | 7 ++++ .../fixDocstringRemove.before.py | 8 ++++ .../PyChangeSignatureTest.java | 7 +++- 6 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 python/testData/refactoring/changeSignature/fixDocstringRemove.after.py create mode 100644 python/testData/refactoring/changeSignature/fixDocstringRemove.before.py diff --git a/python/src/com/jetbrains/python/editor/PythonDocCommentUtil.java b/python/src/com/jetbrains/python/editor/PythonDocCommentUtil.java index 4b7d1961f44e..05ef0b5e116b 100644 --- a/python/src/com/jetbrains/python/editor/PythonDocCommentUtil.java +++ b/python/src/com/jetbrains/python/editor/PythonDocCommentUtil.java @@ -1,5 +1,6 @@ package com.jetbrains.python.editor; +import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiWhiteSpace; @@ -56,4 +57,38 @@ public class PythonDocCommentUtil { } return ws+suffix; } + + static public String removeParamFromDocstring(String text, String prefix, String paramName) { + StringBuilder newText = new StringBuilder(); + String[] lines = LineTokenizer.tokenize(text, true); + boolean skipNext = false; + for (String line : lines) { + if (line.contains(prefix)) { + String[] subLines = line.split(" "); + boolean lookNext = false; + boolean add = true; + for (String s : subLines) { + if (s.trim().equals(prefix + "param")) { + lookNext = true; + } + if (lookNext && s.trim().endsWith(":")) { + String tmp = s.trim().substring(0, s.trim().length() - 1); + if (paramName.equals(tmp)) { + lookNext = false; + skipNext = true; + add = false; + } + } + } + if (add) { + newText.append(line); + skipNext = false; + } + } + else if (!skipNext || line.contains("\"\"\"") || line.contains("'''")) { + newText.append(line); + } + } + return newText.toString(); + } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java index d35acccaa8db..fbc4ad937a57 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java @@ -6,7 +6,6 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; @@ -14,6 +13,7 @@ import com.jetbrains.python.PyBundle; import com.jetbrains.python.documentation.PyDocstringGenerator; import com.jetbrains.python.documentation.PyDocumentationSettings; import com.jetbrains.python.documentation.PythonDocumentationProvider; +import com.jetbrains.python.editor.PythonDocCommentUtil; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -104,7 +104,7 @@ public class DocstringQuickFix implements LocalQuickFix { replacement = createMissingReplacement(docStringOwner); } if (myUnexpected != null) { - replacement = createUnexpectedReplacement(replacement); + replacement = PythonDocCommentUtil.removeParamFromDocstring(replacement, myPrefix, myUnexpected); } if (!replacement.equals(docStringExpression.getText())) { PyExpression str = elementGenerator.createDocstring(replacement).getExpression(); @@ -112,40 +112,6 @@ public class DocstringQuickFix implements LocalQuickFix { } } - private String createUnexpectedReplacement(String text) { - StringBuilder newText = new StringBuilder(); - String[] lines = LineTokenizer.tokenize(text, true); - boolean skipNext = false; - for (String line : lines) { - if (line.contains(myPrefix)) { - String[] subLines = line.split(" "); - boolean lookNext = false; - boolean add = true; - for (String s : subLines) { - if (s.trim().equals(myPrefix + "param")) { - lookNext = true; - } - if (lookNext && s.trim().endsWith(":")) { - String tmp = s.trim().substring(0, s.trim().length() - 1); - if (myUnexpected.equals(tmp)) { - lookNext = false; - skipNext = true; - add = false; - } - } - } - if (add) { - newText.append(line); - skipNext = false; - } - } - else if (!skipNext || line.contains("\"\"\"") || line.contains("'''")) { - newText.append(line); - } - } - return newText.toString(); - } - private String createMissingReplacement(PyDocStringOwner docStringOwner) { return new PyDocstringGenerator(docStringOwner).withParam("param", myMissingText).docStringAsText(); } diff --git a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java index 627591004ccc..9d0efbcd18c1 100644 --- a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java @@ -11,8 +11,12 @@ import com.intellij.refactoring.changeSignature.ParameterInfo; import com.intellij.refactoring.rename.RenameUtil; import com.intellij.usageView.UsageInfo; import com.intellij.util.Query; +import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.PythonLanguage; +import com.jetbrains.python.documentation.PyDocstringGenerator; +import com.jetbrains.python.documentation.PyDocumentationSettings; +import com.jetbrains.python.editor.PythonDocCommentUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.search.PyOverridingMethodsSearch; import com.jetbrains.python.refactoring.PyRefactoringUtil; @@ -22,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Set; /** * User : ktisha @@ -194,17 +199,46 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } } if (changeInfo.isParameterSetOrOrderChanged()) { + + fixDoc(changeInfo, function); updateParameterList(changeInfo, function); } } + private static void fixDoc(PyChangeInfo changeInfo, @NotNull PyFunction function) { + final PyStringLiteralExpression docStringExpression = function.getDocStringExpression(); + if (docStringExpression == null) return; + final PyParameterInfo[] parameters = changeInfo.getNewParameters(); + Set names = new HashSet(); + for (PyParameterInfo info : parameters) { + names.add(info.getName()); + } + for (PyParameter p : function.getParameterList().getParameters()) { + if (!names.contains(p.getName())) { + PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(function.getProject()); + String prefix = documentationSettings.isEpydocFormat(docStringExpression.getContainingFile())? "@" : ":"; + final String replacement = PythonDocCommentUtil.removeParamFromDocstring(docStringExpression.getText(), prefix, p.getName()); + PyExpression str = PyElementGenerator.getInstance(function.getProject()).createDocstring(replacement).getExpression(); + docStringExpression.replace(str); + } + } + } + private static void updateParameterList(PyChangeInfo changeInfo, PyFunction baseMethod) { final PsiElement parameterList = baseMethod.getParameterList(); final PyParameterInfo[] parameters = changeInfo.getNewParameters(); StringBuilder builder = new StringBuilder("def foo("); - for(int i = 0; i != parameters.length; ++i) { + final PyStringLiteralExpression docstring = baseMethod.getDocStringExpression(); + for (int i = 0; i != parameters.length; ++i) { PyParameterInfo info = parameters[i]; + + if (docstring != null && info.getOldIndex() == -1) { + final String replacement = new PyDocstringGenerator(baseMethod).withParam("param", info.getName()).docStringAsText(); + PyExpression str = PyElementGenerator.getInstance(baseMethod.getProject()).createDocstring(replacement).getExpression(); + docstring.replace(str); + } + builder.append(info.getName()); final String defaultValue = info.getDefaultValue(); if (defaultValue != null && info.getDefaultInSignature() && !StringUtil.isEmpty(defaultValue)) { diff --git a/python/testData/refactoring/changeSignature/fixDocstringRemove.after.py b/python/testData/refactoring/changeSignature/fixDocstringRemove.after.py new file mode 100644 index 000000000000..8bf215579b02 --- /dev/null +++ b/python/testData/refactoring/changeSignature/fixDocstringRemove.after.py @@ -0,0 +1,7 @@ +def foo(a): + """ + :param a: + """ + pass + +foo("a") diff --git a/python/testData/refactoring/changeSignature/fixDocstringRemove.before.py b/python/testData/refactoring/changeSignature/fixDocstringRemove.before.py new file mode 100644 index 000000000000..52301e8f243a --- /dev/null +++ b/python/testData/refactoring/changeSignature/fixDocstringRemove.before.py @@ -0,0 +1,8 @@ +def foo(a, d): + """ + :param a: + :param d: + """ + pass + +foo("a", "b") diff --git a/python/testSrc/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureTest.java b/python/testSrc/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureTest.java index 34d2b5643026..c35ebc3b26d8 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureTest.java @@ -56,8 +56,13 @@ public class PyChangeSignatureTest extends PyTestCase { doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "a", null, false), new PyParameterInfo(1, "d1", "1", true))); } + public void testFixDocstringRemove() { + doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "a", 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))); + doChangeSignatureTest(null, Arrays.asList(new PyParameterInfo(0, "self", null, false), new PyParameterInfo(1, "a", null, true), + new PyParameterInfo(-1, "b", "2", false))); } public void doChangeSignatureTest(@Nullable String newName, @Nullable List parameters) {