fixed docstring update while change signature

This commit is contained in:
Ekaterina Tuzova
2012-11-23 16:50:38 +04:00
parent 7dbfef52e9
commit 3e33798ac9
6 changed files with 93 additions and 38 deletions
@@ -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();
}
}
@@ -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();
}
@@ -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<String> names = new HashSet<String>();
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)) {
@@ -0,0 +1,7 @@
def foo(a):
"""
:param a:
"""
pass
foo("a")
@@ -0,0 +1,8 @@
def foo(a, d):
"""
:param a:
:param d:
"""
pass
foo("a", "b")
@@ -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<PyParameterInfo> parameters) {