mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
More flexible API for PyDocstringGenerator
This commit is contained in:
+2
-2
@@ -67,7 +67,7 @@ public class PyGenerateDocstringIntention extends BaseIntentionAction {
|
||||
|
||||
private boolean isAvailableForFunction(PyFunction function) {
|
||||
if (function.getDocStringValue() != null) {
|
||||
final PyDocstringGenerator docstringGenerator = new PyDocstringGenerator(function);
|
||||
final PyDocstringGenerator docstringGenerator = PyDocstringGenerator.forDocStringOwner(function);
|
||||
if (docstringGenerator.hasParametersToAdd()) {
|
||||
myText = PyBundle.message("INTN.add.parameters.to.docstring");
|
||||
return true;
|
||||
@@ -101,7 +101,7 @@ public class PyGenerateDocstringIntention extends BaseIntentionAction {
|
||||
if (!DocStringUtil.ensureNotPlainDocstringFormat(docStringOwner)) {
|
||||
return;
|
||||
}
|
||||
final PyDocstringGenerator docstringGenerator = new PyDocstringGenerator(docStringOwner);
|
||||
final PyDocstringGenerator docstringGenerator = PyDocstringGenerator.forDocStringOwner(docStringOwner);
|
||||
docstringGenerator.addFirstEmptyLine();
|
||||
final PyStringLiteralExpression updated = docstringGenerator.buildAndInsert().getDocStringExpression();
|
||||
if (updated != null && editor != null) {
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention {
|
||||
|
||||
final boolean isReturn = "rtype".equals(kind);
|
||||
|
||||
final PyDocstringGenerator docstringGenerator = new PyDocstringGenerator(pyFunction);
|
||||
final PyDocstringGenerator docstringGenerator = PyDocstringGenerator.forDocStringOwner(pyFunction);
|
||||
docstringGenerator.addFirstEmptyLine();
|
||||
final PySignature signature = PySignatureCacheManager.getInstance(pyFunction.getProject()).findSignature(pyFunction);
|
||||
final String name = isReturn ? "" : StringUtil.notNullize(problemElement.getName());
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.documentation;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -33,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
@@ -53,26 +55,65 @@ import java.util.Set;
|
||||
* @author traff
|
||||
*/
|
||||
public class PyDocstringGenerator {
|
||||
|
||||
public static final String TRIPLE_DOUBLE_QUOTES = "\"\"\"";
|
||||
public static final String TRIPLE_SINGLE_QUOTES = "'''";
|
||||
|
||||
private final List<DocstringParam> myAddedParams = Lists.newArrayList();
|
||||
private final List<DocstringParam> myRemovedParams = Lists.newArrayList();
|
||||
// Updated after buildAndInsert
|
||||
@NotNull
|
||||
private PyDocStringOwner myDocStringOwner;
|
||||
private final String myDocStringText;
|
||||
|
||||
// Updated after buildAndInsert()
|
||||
@Nullable private PyDocStringOwner myDocStringOwner;
|
||||
private final String myDocStringIndent;
|
||||
private final DocStringFormat myDocStringFormat;
|
||||
|
||||
private boolean myUseTypesFromDebuggerSignature = true;
|
||||
private boolean myNewMode = false; // true - generate new string, false - update existing
|
||||
private boolean myAddFirstEmptyLine = false;
|
||||
private boolean myParametersPrepared = false;
|
||||
private boolean myAlwaysGenerateReturn;
|
||||
private String myQuotes = "\"\"\"";
|
||||
private String myQuotes = TRIPLE_DOUBLE_QUOTES;
|
||||
|
||||
public PyDocstringGenerator(@NotNull PyDocStringOwner docStringOwner) {
|
||||
private PyDocstringGenerator(@Nullable PyDocStringOwner docStringOwner,
|
||||
@NotNull DocStringFormat format,
|
||||
@NotNull String indentation,
|
||||
@NotNull String docStringText) {
|
||||
myDocStringOwner = docStringOwner;
|
||||
final PyStringLiteralExpression docStringExpression = myDocStringOwner.getDocStringExpression();
|
||||
myNewMode = docStringExpression == null;
|
||||
myDocStringIndent = indentation;
|
||||
myDocStringFormat = format;
|
||||
myDocStringText = docStringText;
|
||||
myNewMode = StringUtil.isEmpty(myDocStringText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator forDocStringOwner(@NotNull PyDocStringOwner owner) {
|
||||
String indentation = "";
|
||||
if (owner instanceof PyStatementListContainer) {
|
||||
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)owner).getStatementList());
|
||||
}
|
||||
final String docStringText = owner.getDocStringExpression() == null ? "" : owner.getDocStringExpression().getText();
|
||||
return new PyDocstringGenerator(owner, DocStringUtil.getDocStringFormat(owner), indentation, docStringText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator create(@NotNull DocStringFormat format, @NotNull String indentation) {
|
||||
return new PyDocstringGenerator(null, format, indentation, "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator update(@NotNull PyStringLiteralExpression docString) {
|
||||
return new PyDocstringGenerator(PsiTreeUtil.getParentOfType(docString, PyDocStringOwner.class),
|
||||
DocStringUtil.getDocStringFormat(docString),
|
||||
PyIndentUtil.getElementIndent(docString), docString.getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator update(@NotNull DocStringFormat format,
|
||||
@NotNull String indentation,
|
||||
@NotNull String text) {
|
||||
return new PyDocstringGenerator(null, format, indentation, text);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withParam(@NotNull String name) {
|
||||
return withParamTypedByName(name, null);
|
||||
@@ -177,7 +218,7 @@ public class PyDocstringGenerator {
|
||||
if (myDocStringOwner instanceof PyFunction && myUseTypesFromDebuggerSignature) {
|
||||
signature = PySignatureCacheManager.getInstance(myDocStringOwner.getProject()).findSignature((PyFunction)myDocStringOwner);
|
||||
}
|
||||
final DocStringFormat format = getDocStringFormat();
|
||||
final DocStringFormat format = myDocStringFormat;
|
||||
final ArrayList<DocstringParam> filtered = Lists.newArrayList();
|
||||
final Set<Pair<String, Boolean>> processed = Sets.newHashSet();
|
||||
for (DocstringParam param : myAddedParams) {
|
||||
@@ -231,25 +272,17 @@ public class PyDocstringGenerator {
|
||||
|
||||
@Nullable
|
||||
private PyStringLiteralExpression getDocStringExpression() {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
return myDocStringOwner.getDocStringExpression();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DocStringFormat getDocStringFormat() {
|
||||
return DocStringUtil.getDocStringFormat(myDocStringOwner);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StructuredDocString getStructuredDocString() {
|
||||
final PyStringLiteralExpression expression = getDocStringExpression();
|
||||
final DocStringFormat format = getDocStringFormat();
|
||||
if (format == DocStringFormat.PLAIN || expression == null) {
|
||||
return null;
|
||||
}
|
||||
return DocStringUtil.parseDocString(format, expression);
|
||||
return myDocStringText.isEmpty() ? null : DocStringUtil.parseDocString(myDocStringFormat, myDocStringText);
|
||||
}
|
||||
|
||||
public void startTemplate() {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
final PyStringLiteralExpression docStringExpression = getDocStringExpression();
|
||||
assert docStringExpression != null;
|
||||
|
||||
@@ -260,7 +293,7 @@ public class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
final DocstringParam paramToEdit = getParamToEdit();
|
||||
final DocStringFormat format = getDocStringFormat();
|
||||
final DocStringFormat format = myDocStringFormat;
|
||||
if (format == DocStringFormat.PLAIN) {
|
||||
return;
|
||||
}
|
||||
@@ -298,15 +331,6 @@ 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();
|
||||
@@ -320,8 +344,8 @@ public class PyDocstringGenerator {
|
||||
|
||||
@NotNull
|
||||
private String createDocString() {
|
||||
final String indentation = getDocStringIndentation();
|
||||
final DocStringFormat format = getDocStringFormat();
|
||||
final String indentation = myDocStringIndent;
|
||||
final DocStringFormat format = myDocStringFormat;
|
||||
DocStringBuilder builder = null;
|
||||
if (format == DocStringFormat.EPYTEXT || format == DocStringFormat.REST) {
|
||||
builder = new TagBasedDocStringBuilder(format == DocStringFormat.EPYTEXT ? "@" : ":");
|
||||
@@ -396,21 +420,19 @@ public class PyDocstringGenerator {
|
||||
|
||||
@NotNull
|
||||
private String updateDocString() {
|
||||
final DocStringFormat format = getDocStringFormat();
|
||||
DocStringUpdater updater = null;
|
||||
final String docStringIndent = getDocStringIndentation();
|
||||
if (format == DocStringFormat.EPYTEXT || format == DocStringFormat.REST) {
|
||||
final String prefix = format == DocStringFormat.EPYTEXT ? "@" : ":";
|
||||
if (myDocStringFormat == DocStringFormat.EPYTEXT || myDocStringFormat == DocStringFormat.REST) {
|
||||
final String prefix = myDocStringFormat == DocStringFormat.EPYTEXT ? "@" : ":";
|
||||
//noinspection unchecked,ConstantConditions
|
||||
updater = new TagBasedDocStringUpdater((TagBasedDocString)getStructuredDocString(), prefix, docStringIndent);
|
||||
updater = new TagBasedDocStringUpdater((TagBasedDocString)getStructuredDocString(), prefix, myDocStringIndent);
|
||||
}
|
||||
else if (format == DocStringFormat.GOOGLE) {
|
||||
else if (myDocStringFormat == DocStringFormat.GOOGLE) {
|
||||
//noinspection ConstantConditions
|
||||
updater = new GoogleCodeStyleDocStringUpdater((SectionBasedDocString)getStructuredDocString(), docStringIndent);
|
||||
updater = new GoogleCodeStyleDocStringUpdater((SectionBasedDocString)getStructuredDocString(), myDocStringIndent);
|
||||
}
|
||||
else if (format == DocStringFormat.NUMPY) {
|
||||
else if (myDocStringFormat == DocStringFormat.NUMPY) {
|
||||
//noinspection ConstantConditions
|
||||
updater = new NumpyDocStringUpdater((SectionBasedDocString)getStructuredDocString(), docStringIndent);
|
||||
updater = new NumpyDocStringUpdater((SectionBasedDocString)getStructuredDocString(), myDocStringIndent);
|
||||
}
|
||||
if (updater != null) {
|
||||
for (DocstringParam param : myAddedParams) {
|
||||
@@ -440,6 +462,7 @@ public class PyDocstringGenerator {
|
||||
|
||||
@NotNull
|
||||
public PyDocStringOwner buildAndInsert() {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
final String replacementText = buildDocString();
|
||||
|
||||
final Project project = myDocStringOwner.getProject();
|
||||
|
||||
@@ -261,7 +261,7 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
if (docOwner != null) {
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
final String quotes = editor.getDocument().getText(TextRange.from(caretOffset - 3, 3));
|
||||
final String docString = new PyDocstringGenerator(docOwner)
|
||||
final String docString = PyDocstringGenerator.forDocStringOwner(docOwner)
|
||||
.forceAddReturn()
|
||||
.withQuotes(quotes)
|
||||
.forceNewMode()
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PythonSpaceHandler extends TypedHandlerDelegate {
|
||||
if (docOwner != null) {
|
||||
final Document document = editor.getDocument();
|
||||
final String quotes = document.getText(TextRange.from(expectedStringStart, 3));
|
||||
final String docString = new PyDocstringGenerator(docOwner)
|
||||
final String docString = PyDocstringGenerator.forDocStringOwner(docOwner)
|
||||
.forceNewMode()
|
||||
.withQuotes(quotes)
|
||||
.forceAddReturn()
|
||||
|
||||
@@ -88,7 +88,7 @@ public class DocstringQuickFix implements LocalQuickFix {
|
||||
return;
|
||||
}
|
||||
if (docStringExpression != null) {
|
||||
final PyDocstringGenerator generator = new PyDocstringGenerator(docStringOwner);
|
||||
final PyDocstringGenerator generator = PyDocstringGenerator.forDocStringOwner(docStringOwner);
|
||||
if (myMissingText != null) {
|
||||
generator.withParam(myMissingText);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
new PyDocstringGenerator(pyFunction).withoutParam(paramName).buildAndInsert();
|
||||
PyDocstringGenerator.forDocStringOwner(pyFunction).withoutParam(paramName).buildAndInsert();
|
||||
}
|
||||
}
|
||||
element.delete();
|
||||
|
||||
+10
-4
@@ -335,7 +335,7 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
|
||||
}
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(function);
|
||||
if (module == null) return;
|
||||
final PyDocstringGenerator generator = new PyDocstringGenerator(function);
|
||||
final PyDocstringGenerator generator = PyDocstringGenerator.forDocStringOwner(function);
|
||||
for (PyParameter p : function.getParameterList().getParameters()) {
|
||||
final String paramName = p.getName();
|
||||
if (!names.contains(paramName) && paramName != null) {
|
||||
@@ -353,7 +353,9 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
|
||||
final PyStringLiteralExpression docstring = baseMethod.getDocStringExpression();
|
||||
final PyParameter[] oldParameters = baseMethod.getParameterList().getParameters();
|
||||
final PyElementGenerator generator = PyElementGenerator.getInstance(baseMethod.getProject());
|
||||
for (int i = 0; i != parameters.length; ++i) {
|
||||
final PyDocstringGenerator docStringGenerator = PyDocstringGenerator.forDocStringOwner(baseMethod);
|
||||
boolean newParameterInDocString = false;
|
||||
for (int i = 0; i < parameters.length; ++i) {
|
||||
final PyParameterInfo info = parameters[i];
|
||||
|
||||
final int oldIndex = info.getOldIndex();
|
||||
@@ -362,7 +364,8 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
|
||||
}
|
||||
|
||||
if (docstring != null && oldIndex < 0) {
|
||||
new PyDocstringGenerator(baseMethod).withParam(info.getName()).buildAndInsert();
|
||||
newParameterInDocString = true;
|
||||
docStringGenerator.withParam(info.getName());
|
||||
}
|
||||
|
||||
if (oldIndex < oldParameters.length) {
|
||||
@@ -381,9 +384,12 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
|
||||
if (defaultValue != null && info.getDefaultInSignature() && StringUtil.isNotEmpty(defaultValue)) {
|
||||
builder.append(" = ").append(defaultValue);
|
||||
}
|
||||
|
||||
}
|
||||
builder.append("): pass");
|
||||
|
||||
if (newParameterInDocString) {
|
||||
docStringGenerator.buildAndInsert();
|
||||
}
|
||||
|
||||
final PyParameterList newParameterList = generator.createFromText(LanguageLevel.forElement(baseMethod),
|
||||
PyFunction.class,
|
||||
|
||||
Reference in New Issue
Block a user