Docstring parameters are removed via PyDocstringGenerator as well

This commit is contained in:
Mikhail Golubev
2015-09-02 14:35:33 +03:00
parent a6d0b050de
commit f05d9dde14
5 changed files with 47 additions and 82 deletions
@@ -29,10 +29,6 @@ import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.documentation.docstrings.DocStringUpdater;
import com.jetbrains.python.documentation.docstrings.GoogleCodeStyleDocStringUpdater;
import com.jetbrains.python.documentation.docstrings.NumpyDocStringUpdater;
import com.jetbrains.python.documentation.docstrings.TagBasedDocStringUpdater;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
@@ -41,8 +37,6 @@ 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;
@@ -268,44 +262,4 @@ public class DocStringUtil {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(getModuleForElement(anchor));
return settings.getFormatForFile(anchor.getContainingFile());
}
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;
switch (format) {
case EPYTEXT:
final EpydocString epyParsed = (EpydocString)parseDocString(format, docString);
updater = new TagBasedDocStringUpdater(epyParsed, "@", PyIndentUtil.getElementIndent(docString));
break;
case REST:
final SphinxDocString restParsed = (SphinxDocString)parseDocString(format, docString);
updater = new TagBasedDocStringUpdater(restParsed, ":", PyIndentUtil.getElementIndent(docString));
break;
case GOOGLE:
final GoogleCodeStyleDocString googleParsed = (GoogleCodeStyleDocString)parseDocString(format, docString);
updater = new GoogleCodeStyleDocStringUpdater(googleParsed, PyIndentUtil.getElementIndent(docString));
break;
case NUMPY:
final NumpyDocString numpyParsed = (NumpyDocString)parseDocString(format, docString);
updater = new NumpyDocStringUpdater(numpyParsed, PyIndentUtil.getElementIndent(docString));
break;
default:
return docString;
}
for (String name : paramNames) {
updater.removeParameter(name);
}
final String newText = updater.getDocStringText();
final PyExpressionStatement replacement = PyElementGenerator.getInstance(docString.getProject()).createDocstring(newText);
return (PyStringLiteralExpression)docString.replace(replacement.getExpression());
}
@NotNull
public static PyStringLiteralExpression removeParamsFromDocString(@NotNull PyStringLiteralExpression docString,
@NotNull String... paramNames) {
return removeParamsFromDocString(docString, Arrays.asList(paramNames));
}
}
@@ -49,7 +49,8 @@ import java.util.List;
*/
public class PyDocstringGenerator {
private final List<DocstringParam> myParams = Lists.newArrayList();
private final List<DocstringParam> myAddedParams = Lists.newArrayList();
private final List<DocstringParam> myRemovedParams = Lists.newArrayList();
// Updated after buildAndInsert
@NotNull
private PyDocStringOwner myDocStringOwner;
@@ -72,15 +73,21 @@ public class PyDocstringGenerator {
return withParamTypedByName(name, null);
}
@NotNull
public PyDocstringGenerator withoutParam(@NotNull String name) {
myRemovedParams.add(new DocstringParam(name, null, false));
return this;
}
@NotNull
public PyDocstringGenerator withParamTypedByName(@NotNull String name, @Nullable String type) {
myParams.add(new DocstringParam(name, type, false));
myAddedParams.add(new DocstringParam(name, type, false));
return this;
}
@NotNull
public PyDocstringGenerator withReturnValue(@Nullable String type) {
myParams.add(new DocstringParam("", type, true));
myAddedParams.add(new DocstringParam("", type, true));
return this;
}
@@ -120,8 +127,8 @@ public class PyDocstringGenerator {
}
private void prepareParameters() {
// Populate parameter list, if no one was specified explicitly
if (!myParametersPrepared && myParams.isEmpty()) {
// Populate parameter list, if no one was specified explicitly to add or remove
if (!myParametersPrepared && myAddedParams.isEmpty() && myRemovedParams.isEmpty()) {
if (myDocStringOwner instanceof PyFunction) {
PySignature signature = null;
if (myUseTypesFromDebuggerSignature) {
@@ -151,7 +158,7 @@ public class PyDocstringGenerator {
statementList.accept(visitor);
if (visitor.myHasReturn || myAlwaysGenerateReturn) {
// will add :return: placeholder in Sphinx/Epydoc docstrings
myParams.add(new DocstringParam("", null, true));
myAddedParams.add(new DocstringParam("", null, true));
if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
withReturnValue("");
}
@@ -162,17 +169,17 @@ public class PyDocstringGenerator {
if (format == DocStringFormat.GOOGLE || format == DocStringFormat.NUMPY) {
// Google and Numpy docstring formats combine type and description in single declaration, thus
// if both declaration with type and without it are requested, we should filter out duplicates
final ArrayList<DocstringParam> copy = new ArrayList<DocstringParam>(myParams);
final ArrayList<DocstringParam> copy = new ArrayList<DocstringParam>(myAddedParams);
for (final DocstringParam param : copy) {
if (param.getType() == null) {
final DocstringParam sameParamWithType = ContainerUtil.find(myParams, new Condition<DocstringParam>() {
final DocstringParam sameParamWithType = ContainerUtil.find(myAddedParams, new Condition<DocstringParam>() {
@Override
public boolean value(DocstringParam other) {
return other.isReturnValue() == param.isReturnValue() && other.getName().equals(param.getName()) && other.getType() != null;
}
});
if (sameParamWithType != null) {
myParams.remove(param);
myAddedParams.remove(param);
}
}
}
@@ -182,7 +189,7 @@ public class PyDocstringGenerator {
public boolean hasParametersToAdd() {
prepareParameters();
return !myParams.isEmpty();
return !myAddedParams.isEmpty();
}
@Nullable
@@ -211,7 +218,7 @@ public class PyDocstringGenerator {
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(docStringExpression);
if (myParams.size() > 1) {
if (myAddedParams.size() > 1) {
throw new IllegalArgumentException("TemplateBuilder can be created only for one parameter");
}
@@ -254,6 +261,15 @@ public class PyDocstringGenerator {
}
}
@NotNull
private String getDocStringIndentation() {
String indentation = "";
if (myDocStringOwner instanceof PyStatementListContainer) {
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)myDocStringOwner).getStatementList());
}
return indentation;
}
@NotNull
public String buildDocString() {
prepareParameters();
@@ -276,7 +292,7 @@ public class PyDocstringGenerator {
if (myAddFirstEmptyLine) {
tagBuilder.addEmptyLine();
}
for (DocstringParam param : myParams) {
for (DocstringParam param : myAddedParams) {
if (param.isReturnValue()) {
if (param.getType() != null) {
tagBuilder.addReturnValueType(param.getType());
@@ -301,7 +317,7 @@ public class PyDocstringGenerator {
if (myAddFirstEmptyLine) {
sectionBuilder.addEmptyLine();
}
final List<DocstringParam> parameters = ContainerUtil.findAll(myParams, new Condition<DocstringParam>() {
final List<DocstringParam> parameters = ContainerUtil.findAll(myAddedParams, new Condition<DocstringParam>() {
@Override
public boolean value(DocstringParam param) {
return !param.isReturnValue();
@@ -314,7 +330,7 @@ public class PyDocstringGenerator {
}
}
final List<DocstringParam> returnValues = ContainerUtil.findAll(myParams, new Condition<DocstringParam>() {
final List<DocstringParam> returnValues = ContainerUtil.findAll(myAddedParams, new Condition<DocstringParam>() {
@Override
public boolean value(DocstringParam param) {
return param.isReturnValue();
@@ -341,15 +357,6 @@ public class PyDocstringGenerator {
return myQuotes + '\n' + indentation + myQuotes;
}
@NotNull
private String getDocStringIndentation() {
String indentation = "";
if (myDocStringOwner instanceof PyStatementListContainer) {
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)myDocStringOwner).getStatementList());
}
return indentation;
}
@NotNull
private String updateDocString() {
final DocStringFormat format = getDocStringFormat();
@@ -369,7 +376,7 @@ public class PyDocstringGenerator {
updater = new NumpyDocStringUpdater((SectionBasedDocString)getStructuredDocString(), docStringIndent);
}
if (updater != null) {
for (DocstringParam param : myParams) {
for (DocstringParam param : myAddedParams) {
if (param.isReturnValue()) {
updater.addReturnValue(param.getType());
}
@@ -377,16 +384,21 @@ public class PyDocstringGenerator {
updater.addParameter(param.getName(), param.getType());
}
}
for (DocstringParam param : myRemovedParams) {
if (!param.isReturnValue()) {
updater.removeParameter(param.getName());
}
}
return updater.getDocStringText();
}
return myQuotes + myQuotes;
}
private DocstringParam getParamToEdit() {
if (myParams.size() == 0) {
if (myAddedParams.size() == 0) {
throw new IllegalStateException("We should have at least one param to edit");
}
return myParams.get(0);
return myAddedParams.get(0);
}
@NotNull
@@ -26,7 +26,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.intentions.PyGenerateDocstringIntention;
import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.documentation.PyDocstringGenerator;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyDocStringOwner;
@@ -89,12 +88,14 @@ public class DocstringQuickFix implements LocalQuickFix {
return;
}
if (docStringExpression != null) {
final PyDocstringGenerator generator = new PyDocstringGenerator(docStringOwner);
if (myMissingText != null) {
new PyDocstringGenerator(docStringOwner).withParam(myMissingText).buildAndInsert();
generator.withParam(myMissingText);
}
else if (myUnexpected != null) {
DocStringUtil.removeParamsFromDocString(docStringExpression, myUnexpected);
generator.withoutParam(myUnexpected);
}
generator.buildAndInsert();
}
}
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageInfo;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.documentation.PyDocstringGenerator;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
@@ -73,10 +73,9 @@ public class PyRemoveParameterQuickFix implements LocalQuickFix {
final PyStringLiteralExpression expression = pyFunction.getDocStringExpression();
final String paramName = ((PyParameter)element).getName();
if (expression != null && paramName != null) {
DocStringUtil.removeParamsFromDocString(expression, paramName);
new PyDocstringGenerator(pyFunction).withoutParam(paramName).buildAndInsert();
}
}
element.delete();
}
}
@@ -33,7 +33,6 @@ import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.documentation.PyDocstringGenerator;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
@@ -336,14 +335,14 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
}
final Module module = ModuleUtilCore.findModuleForPsiElement(function);
if (module == null) return;
final List<String> removedParamNames = new ArrayList<String>();
final PyDocstringGenerator generator = new PyDocstringGenerator(function);
for (PyParameter p : function.getParameterList().getParameters()) {
final String paramName = p.getName();
if (!names.contains(paramName) && paramName != null) {
removedParamNames.add(paramName);
generator.withoutParam(paramName);
}
}
DocStringUtil.removeParamsFromDocString(docStringExpression, removedParamNames);
generator.buildAndInsert();
}
private static void updateParameterList(PyChangeInfo changeInfo, PyFunction baseMethod) {