From f05d9dde1491adb089a8698cf7d059e83d82cade Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 28 Aug 2015 13:55:05 +0300 Subject: [PATCH] Docstring parameters are removed via PyDocstringGenerator as well --- .../python/documentation/DocStringUtil.java | 46 ------------- .../documentation/PyDocstringGenerator.java | 64 +++++++++++-------- .../quickfix/DocstringQuickFix.java | 7 +- .../quickfix/PyRemoveParameterQuickFix.java | 5 +- .../PyChangeSignatureUsageProcessor.java | 7 +- 5 files changed, 47 insertions(+), 82 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index e340160f5bbc..320392860333 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -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 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)); - } } diff --git a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java index e61c3ef58de0..ffe0697e5859 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java +++ b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java @@ -49,7 +49,8 @@ import java.util.List; */ public class PyDocstringGenerator { - private final List myParams = Lists.newArrayList(); + private final List myAddedParams = Lists.newArrayList(); + private final List 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 copy = new ArrayList(myParams); + final ArrayList copy = new ArrayList(myAddedParams); for (final DocstringParam param : copy) { if (param.getType() == null) { - final DocstringParam sameParamWithType = ContainerUtil.find(myParams, new Condition() { + final DocstringParam sameParamWithType = ContainerUtil.find(myAddedParams, new Condition() { @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 parameters = ContainerUtil.findAll(myParams, new Condition() { + final List parameters = ContainerUtil.findAll(myAddedParams, new Condition() { @Override public boolean value(DocstringParam param) { return !param.isReturnValue(); @@ -314,7 +330,7 @@ public class PyDocstringGenerator { } } - final List returnValues = ContainerUtil.findAll(myParams, new Condition() { + final List returnValues = ContainerUtil.findAll(myAddedParams, new Condition() { @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 diff --git a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java index 0bdd733da3a2..b46b0c2091c8 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java @@ -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(); } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveParameterQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveParameterQuickFix.java index bc41e03378db..6ef60e59d375 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveParameterQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveParameterQuickFix.java @@ -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(); } } diff --git a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java index 31b157373b15..3dc62b258a28 100644 --- a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureUsageProcessor.java @@ -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 removedParamNames = new ArrayList(); + 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) {