Fix broken tests of docstring generation on enter

This commit is contained in:
Mikhail Golubev
2015-09-02 14:34:58 +03:00
parent c07062200f
commit b3e325357f
4 changed files with 72 additions and 44 deletions
@@ -103,8 +103,12 @@ public class PyGenerateDocstringIntention extends BaseIntentionAction {
}
final PyDocstringGenerator docstringGenerator = new PyDocstringGenerator(docStringOwner);
if (docStringOwner instanceof PyFunction) {
docstringGenerator.useTypesFromDebuggerSignature(true);
docstringGenerator.withDefaultParameters();
docstringGenerator
.useTypesFromDebuggerSignature(true)
.addReturn()
.withDefaultParameters()
.addFirstEmptyLine();
if (docStringOwner.getDocStringValue() == null) {
docstringGenerator.addReturn();
}
@@ -78,6 +78,7 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention {
final boolean isReturn = "rtype".equals(kind);
final PyDocstringGenerator docstringGenerator = new PyDocstringGenerator(pyFunction);
docstringGenerator.addFirstEmptyLine();
final PySignature signature = PySignatureCacheManager.getInstance(pyFunction.getProject()).findSignature(pyFunction);
String name = isReturn ? "" : StringUtil.notNullize(problemElement.getName());
final String typeFromSignature = signature != null ? StringUtil.notNullize(signature.getArgTypeQualifiedName(name)) : "";
@@ -30,7 +30,6 @@ import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.debugger.PySignature;
import com.jetbrains.python.debugger.PySignatureCacheManager;
import com.jetbrains.python.documentation.docstrings.DocStringProvider;
import com.jetbrains.python.documentation.docstrings.TagBasedDocStringBuilder;
import com.jetbrains.python.documentation.docstrings.TagBasedDocStringUpdater;
import com.jetbrains.python.psi.*;
@@ -45,30 +44,21 @@ import java.util.List;
*/
public class PyDocstringGenerator {
private List<DocstringParam> myParams = Lists.newArrayList();
private final List<DocstringParam> myParams = Lists.newArrayList();
private boolean myGenerateReturn;
// Updated after buildAndInsert
@NotNull
private PyDocStringOwner myDocStringOwner;
private final StructuredDocString myOriginalDocString;
private final DocStringFormat myDocStringFormat;
private String myQuotes = "\"\"\"";
private boolean myUseTypesFromDebuggerSignature = false;
private boolean myNewMode = false;
private boolean addFirstEmptyLine = false;
private boolean myAddFirstEmptyLine = false;
public PyDocstringGenerator(@NotNull PyDocStringOwner docStringOwner) {
myDocStringOwner = docStringOwner;
myDocStringFormat = DocStringUtil.getDocStringFormat(docStringOwner);
final DocStringProvider provider = myDocStringFormat.getProvider();
final PyStringLiteralExpression docStringExpression = myDocStringOwner.getDocStringExpression();
if (docStringExpression != null) {
myOriginalDocString = provider.parseDocString(docStringExpression);
}
else {
myOriginalDocString = null;
}
myNewMode = docStringExpression == null;
}
@NotNull
@@ -106,6 +96,12 @@ public class PyDocstringGenerator {
return this;
}
@NotNull
public PyDocstringGenerator addFirstEmptyLine() {
myAddFirstEmptyLine = true;
return this;
}
@NotNull
public PyDocstringGenerator forceNewMode() {
myNewMode = true;
@@ -122,18 +118,38 @@ public class PyDocstringGenerator {
signature = PySignatureCacheManager.getInstance(myDocStringOwner.getProject()).findSignature((PyFunction)myDocStringOwner);
}
for (PyParameter param : ((PyFunction)myDocStringOwner).getParameterList().getParameters()) {
String paramName = param.getName();
if (StringUtil.isEmpty(paramName) || param.isSelf() ||
myOriginalDocString != null && myOriginalDocString.getParamTypeSubstring(paramName) != null) {
final String paramName = param.getName();
final StructuredDocString docString = getStructuredDocString();
if (StringUtil.isEmpty(paramName) || param.isSelf() || docString != null && docString.getParamTypeSubstring(paramName) != null) {
continue;
}
String type = signature != null ? signature.getArgTypeQualifiedName(paramName) : null;
final String signatureType = signature != null ? signature.getArgTypeQualifiedName(paramName) : null;
String type = null;
if (signatureType != null) {
type = signatureType;
}
else if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
type = "";
}
withParam(paramName);
if (type != null) {
withParamTypedByName(paramName, type);
}
}
if (myGenerateReturn) {
final RaiseVisitor visitor = new RaiseVisitor();
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
statementList.accept(visitor);
if (visitor.myHasReturn) {
// will add :return: placeholder in Sphinx/Epydoc docstrings
myParams.add(new DocstringParam("", null, true));
if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
withReturnValue("");
}
}
}
}
}
return this;
}
@@ -147,6 +163,21 @@ public class PyDocstringGenerator {
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 format.getProvider().parseDocString(expression);
}
public static String generateRaiseOrReturn(@NotNull PyFunction element, String offset, String prefix, boolean checkReturn) {
final StringBuilder builder = new StringBuilder();
if (checkReturn) {
@@ -238,16 +269,18 @@ public class PyDocstringGenerator {
}
private boolean isNewMode() {
return myNewMode || myOriginalDocString == null;
return myNewMode;
}
@NotNull
private String createDocString() {
if (myDocStringFormat == DocStringFormat.EPYTEXT || myDocStringFormat == DocStringFormat.REST) {
final TagBasedDocStringBuilder builder = new TagBasedDocStringBuilder(myDocStringFormat == DocStringFormat.EPYTEXT ? "@" : ":");
builder.addEmptyLine();
String indentation = getDocStringIndentation();
boolean addedReturn = false;
final String indentation = getDocStringIndentation();
final DocStringFormat format = getDocStringFormat();
if (format == DocStringFormat.EPYTEXT || format == DocStringFormat.REST) {
final TagBasedDocStringBuilder builder = new TagBasedDocStringBuilder(format == DocStringFormat.EPYTEXT ? "@" : ":");
if (myAddFirstEmptyLine) {
builder.addEmptyLine();
}
for (DocstringParam param : myParams) {
if (param.isReturnValue()) {
if (param.getType() != null) {
@@ -256,7 +289,6 @@ public class PyDocstringGenerator {
else {
builder.addReturnValueDescription("");
}
addedReturn = true;
}
else {
if (param.getType() != null) {
@@ -267,18 +299,6 @@ public class PyDocstringGenerator {
}
}
}
if (myGenerateReturn && myDocStringOwner instanceof PyFunction) {
final RaiseVisitor visitor = new RaiseVisitor();
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
statementList.accept(visitor);
if (!addedReturn && visitor.myHasReturn) {
builder.addReturnValueDescription("");
}
if (visitor.myHasRaise) {
builder.addExceptionDescription(visitor.getRaiseTargetText(), "");
}
}
if (builder.getLines().size() > 1) {
return myQuotes + '\n' + builder.buildContent(indentation, true) + '\n' + indentation + myQuotes;
}
@@ -287,7 +307,7 @@ public class PyDocstringGenerator {
}
}
else {
return "";
return myQuotes + '\n' + indentation + myQuotes;
}
}
@@ -302,10 +322,12 @@ public class PyDocstringGenerator {
@NotNull
private String updateDocString() {
if (myDocStringFormat == DocStringFormat.EPYTEXT || myDocStringFormat == DocStringFormat.REST) {
final String prefix = myDocStringFormat == DocStringFormat.EPYTEXT ? "@" : ":";
//noinspection unchecked
TagBasedDocStringUpdater updater = new TagBasedDocStringUpdater((TagBasedDocString)myOriginalDocString, prefix, getDocStringIndentation());
final DocStringFormat format = getDocStringFormat();
if (format == DocStringFormat.EPYTEXT || format == DocStringFormat.REST) {
final String prefix = format == DocStringFormat.EPYTEXT ? "@" : ":";
//noinspection unchecked,ConstantConditions
TagBasedDocStringUpdater updater = new TagBasedDocStringUpdater((TagBasedDocString)getStructuredDocString(),
prefix, getDocStringIndentation());
for (DocstringParam param : myParams) {
if (param.isReturnValue()) {
updater.addReturnValue(param.getType());
@@ -262,8 +262,9 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
final int caretOffset = editor.getCaretModel().getOffset();
final String quotes = editor.getDocument().getText(TextRange.from(caretOffset - 3, 3));
final String docString = new PyDocstringGenerator(docOwner)
.withDefaultParameters()
.addReturn()
.useTypesFromDebuggerSignature(true)
.withDefaultParameters()
.withQuotes(quotes)
.forceNewMode()
.buildDocString();