Support updates of tag bases docstrings. All existing tests pass

This commit is contained in:
Mikhail Golubev
2015-09-02 14:34:47 +03:00
parent d32ba94b25
commit 7c46c74e19
13 changed files with 173 additions and 187 deletions
@@ -174,7 +174,7 @@ public class Substring implements CharSequence {
}
public boolean endsWith(@NotNull String prefix) {
return myString.lastIndexOf(prefix) == length();
return myString.lastIndexOf(prefix) == length() - prefix.length();
}
public int indexOf(@NotNull String s) {
@@ -36,8 +36,13 @@ public abstract class DocStringLineParser {
myLines = Collections.unmodifiableList(content.splitLines());
}
protected static int getIndent(@NotNull CharSequence line) {
return PyIndentUtil.getLineIndentSize(line);
public int getLineIndentSize(int lineNum) {
return PyIndentUtil.getLineIndentSize(getLine(lineNum));
}
@NotNull
public String getLineIndent(int lineNum) {
return PyIndentUtil.getLineIndent(getLine(lineNum)).toString();
}
public boolean isEmptyOrDoesNotExist(int lineNum) {
@@ -53,10 +58,6 @@ public abstract class DocStringLineParser {
return myLines.get(lineNum);
}
public int getLineIndent(int lineNum) {
return getIndent(myLines.get(lineNum));
}
public int getLineByOffset(int offset) {
return StringUtil.countNewLines(myDocStringContent.subSequence(0, offset));
}
@@ -99,7 +99,7 @@ public class GoogleCodeStyleDocString extends SectionBasedDocString {
}
description = colonSeparatedParts.get(1);
// parse line with indentation at least one space greater than indentation of the field
final Pair<List<Substring>, Integer> pair = parseIndentedBlock(lineNum + 1, getIndent(line), sectionIndent);
final Pair<List<Substring>, Integer> pair = parseIndentedBlock(lineNum + 1, getLineIndentSize(lineNum), sectionIndent);
final List<Substring> nestedBlock = pair.getFirst();
if (!nestedBlock.isEmpty()) {
//noinspection ConstantConditions
@@ -78,7 +78,7 @@ public class NumpyDocString extends SectionBasedDocString {
type = name;
name = null;
}
final Pair<List<Substring>, Integer> parsedDescription = parseIndentedBlock(lineNum + 1, getIndent(line), sectionIndent);
final Pair<List<Substring>, Integer> parsedDescription = parseIndentedBlock(lineNum + 1, getLineIndentSize(lineNum), sectionIndent);
final List<Substring> descriptionLines = parsedDescription.getFirst();
if (!descriptionLines.isEmpty()) {
description = mergeSubstrings(descriptionLines.get(0), descriptionLines.get(descriptionLines.size() - 1));
@@ -28,11 +28,11 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
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.*;
import com.jetbrains.python.toolbox.Substring;
import org.jetbrains.annotations.NotNull;
@@ -46,36 +46,25 @@ import java.util.List;
*/
public class PyDocstringGenerator {
@NotNull
private PyDocStringOwner myDocStringOwner;
@Nullable
private PyFunction myFunction;
private final List<DocstringParam> myParams = Lists.newArrayList();
private final Project myProject;
private PyStringLiteralExpression myDocStringExpression;
private final PsiFile myFile;
private boolean myGenerateReturn;
private final StructuredDocString myStructuredDocString;
// Updated after buildAndInsert
@NotNull
private PyDocStringOwner myDocStringOwner;
private final StructuredDocString myOriginalDocString;
private final DocStringFormat myDocStringFormat;
public PyDocstringGenerator(@NotNull PyDocStringOwner docStringOwner) {
myDocStringOwner = docStringOwner;
if (docStringOwner instanceof PyFunction) {
myFunction = (PyFunction)docStringOwner;
}
myProject = myDocStringOwner.getProject();
myFile = myDocStringOwner.getContainingFile();
myDocStringFormat = DocStringUtil.getDocStringFormat(docStringOwner);
final DocStringProvider provider = myDocStringFormat.getProvider();
final PyStringLiteralExpression docStringExpression = myDocStringOwner.getDocStringExpression();
if (docStringExpression != null) {
myStructuredDocString = provider.parseDocString(docStringExpression);
myOriginalDocString = provider.parseDocString(docStringExpression);
}
else {
myStructuredDocString = null;
myOriginalDocString = null;
}
}
@@ -102,6 +91,16 @@ public class PyDocstringGenerator {
return this;
}
@Nullable
private PyStringLiteralExpression getDocStringExpression() {
return myDocStringOwner.getDocStringExpression();
}
@Nullable
private PyFunction getOwnerFunction() {
return PyUtil.as(myDocStringOwner, PyFunction.class);
}
public static String generateRaiseOrReturn(@NotNull PyFunction element, String offset, String prefix, boolean checkReturn) {
final StringBuilder builder = new StringBuilder();
if (checkReturn) {
@@ -131,14 +130,11 @@ public class PyDocstringGenerator {
return builder.toString();
}
private PsiFile getFile() {
return myFile;
}
public void startTemplate() {
assert myDocStringExpression != null;
final PyStringLiteralExpression docStringExpression = getDocStringExpression();
assert docStringExpression != null;
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(myDocStringExpression);
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(docStringExpression);
if (myParams.size() > 1) {
throw new IllegalArgumentException("TemplateBuilder can be created only for one parameter");
@@ -146,7 +142,7 @@ public class PyDocstringGenerator {
final DocstringParam paramToEdit = getParamToEdit();
final String paramName = paramToEdit.getName();
final String stringContent = myDocStringExpression.getStringValue();
final String stringContent = docStringExpression.getStringValue();
final StructuredDocString parsed = DocStringUtil.parse(stringContent);
if (parsed == null) {
return;
@@ -161,15 +157,16 @@ public class PyDocstringGenerator {
if (substring == null) {
return;
}
builder.replaceRange(substring.getTextRange().shiftRight(myDocStringExpression.getStringValueTextRange().getStartOffset()),
builder.replaceRange(substring.getTextRange().shiftRight(docStringExpression.getStringValueTextRange().getStartOffset()),
getDefaultType());
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
final VirtualFile virtualFile = myFile.getVirtualFile();
final VirtualFile virtualFile = myDocStringOwner.getContainingFile().getVirtualFile();
if (virtualFile == null) return;
OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, virtualFile, myDocStringExpression.getTextOffset());
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
final Project project = myDocStringOwner.getProject();
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile, docStringExpression.getTextOffset());
Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
if (targetEditor != null) {
TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
TemplateManager.getInstance(project).startTemplate(targetEditor, template);
}
}
@@ -185,7 +182,7 @@ public class PyDocstringGenerator {
@NotNull
private String buildDocString() {
if (myStructuredDocString != null) {
if (myOriginalDocString != null) {
return updateDocString();
}
else {
@@ -198,10 +195,7 @@ public class PyDocstringGenerator {
if (myDocStringFormat == DocStringFormat.EPYTEXT || myDocStringFormat == DocStringFormat.REST) {
final TagBasedDocStringBuilder builder = new TagBasedDocStringBuilder(myDocStringFormat == DocStringFormat.EPYTEXT ? "@" : ":");
builder.addLine("");
String indentation = "";
if (myDocStringOwner instanceof PyStatementListContainer) {
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)myDocStringOwner).getStatementList());
}
String indentation = getDocStringIndentation();
boolean addedReturn = false;
for (DocstringParam param : myParams) {
if (param.isReturnValue()) {
@@ -246,9 +240,32 @@ public class PyDocstringGenerator {
}
}
@NotNull
private String getDocStringIndentation() {
String indentation = "";
if (myDocStringOwner instanceof PyStatementListContainer) {
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)myDocStringOwner).getStatementList());
}
return indentation;
}
@NotNull
private String updateDocString() {
return "";
if (myDocStringFormat == DocStringFormat.EPYTEXT || myDocStringFormat == DocStringFormat.REST) {
final String prefix = myDocStringFormat == DocStringFormat.EPYTEXT ? "@" : ":";
//noinspection unchecked
TagBasedDocStringUpdater updater = new TagBasedDocStringUpdater((TagBasedDocString)myOriginalDocString, prefix, getDocStringIndentation());
for (DocstringParam param : myParams) {
if (param.isReturnValue()) {
updater.addReturnValue(param.getType());
}
else {
updater.addParameter(param.getName(), param.getType());
}
}
return updater.getDocStringText();
}
return "\"\"\"\"\"\"";
}
public boolean haveParametersToAdd() {
@@ -261,10 +278,10 @@ public class PyDocstringGenerator {
@Override
public boolean apply(DocstringParam param) {
if (param.isReturnValue()) {
return myStructuredDocString.getReturnTypeSubstring() == null;
return myOriginalDocString.getReturnTypeSubstring() == null;
}
else {
return myStructuredDocString.getParamTypeSubstring(param.myName) == null;
return myOriginalDocString.getParamTypeSubstring(param.myName) == null;
}
}
});
@@ -284,44 +301,41 @@ public class PyDocstringGenerator {
public void buildAndInsert() {
final String replacement = buildDocString();
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(myProject);
final Project project = myDocStringOwner.getProject();
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
// update existing docstring
if (myStructuredDocString != null) {
final PyStringLiteralExpression docStringExpression = getDocStringExpression();
if (docStringExpression != null) {
PyExpression str = elementGenerator.createDocstring(replacement).getExpression();
myDocStringExpression.replace(str);
myDocStringOwner = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(myDocStringOwner);
if (myDocStringOwner instanceof PyFunction) {
myFunction = (PyFunction)myDocStringOwner;
}
docStringExpression.replace(str);
}
// create brand new docstring
else {
if (myFunction == null) {
PyFunction function = PyUtil.as(myDocStringOwner, PyFunction.class);
if (function == null) {
throw new IllegalStateException("Should be a function");
}
final PyStatementList statements = myFunction.getStatementList();
final PyStatementList statements = function.getStatementList();
final String indentation = PyIndentUtil.getExpectedElementIndent(statements);
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
final Document document = PsiDocumentManager.getInstance(project).getDocument(myDocStringOwner.getContainingFile());
if (document != null) {
if (PyUtil.onSameLine(statements, myFunction) || statements.getStatements().length == 0) {
PyFunction func = elementGenerator.createFromText(LanguageLevel.forElement(myFunction),
if (PyUtil.onSameLine(statements, function) || statements.getStatements().length == 0) {
PyFunction func = elementGenerator.createFromText(LanguageLevel.forElement(function),
PyFunction.class,
"def " + myFunction.getName() + myFunction.getParameterList().getText() + ":\n" +
"def " + function.getName() + function.getParameterList().getText() + ":\n" +
indentation + replacement + "\n" +
indentation + statements.getText());
myFunction = (PyFunction)myFunction.replace(func);
myDocStringOwner = (PyFunction)function.replace(func);
}
else {
PyExpressionStatement str = elementGenerator.createDocstring(replacement);
statements.addBefore(str, statements.getStatements()[0]);
}
}
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(myFunction);
myDocStringExpression = myFunction.getDocStringExpression();
}
myDocStringOwner = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(myDocStringOwner);
}
public static class DocstringParam {
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.psi.PyIndentUtil;
import com.jetbrains.python.psi.StructuredDocString;
import com.jetbrains.python.toolbox.Substring;
import org.jetbrains.annotations.NonNls;
@@ -146,7 +147,7 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
}
int lineNum = skipEmptyLines(pair.getSecond());
final List<SectionField> fields = new ArrayList<SectionField>();
final int sectionIndent = getIndent(getLine(sectionStartLine));
final int sectionIndent = getLineIndentSize(sectionStartLine);
while (!isSectionBreak(lineNum, sectionIndent)) {
if (!isEmpty(lineNum)) {
final Pair<SectionField, Integer> result = parseSectionField(lineNum, title, sectionIndent);
@@ -217,7 +218,7 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
protected boolean isSectionBreak(int lineNum, int curSectionIndent) {
return lineNum >= getLineCount() ||
isSectionStart(lineNum) ||
(!isEmpty(lineNum) && getIndent(getLine(lineNum)) <= curSectionIndent);
(!isEmpty(lineNum) && getLineIndentSize(lineNum) <= curSectionIndent);
}
/**
@@ -231,7 +232,7 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
final List<Substring> result = new ArrayList<Substring>();
int lastNonEmpty = lineNum - 1;
while (!isSectionBreak(lineNum, sectionIndent)) {
if (getIndent(getLine(lineNum)) > blockIndent) {
if (getLineIndentSize(lineNum) > blockIndent) {
// copy all lines after the last non empty including the current one
for (int i = lastNonEmpty + 1; i <= lineNum; i++) {
result.add(getLine(i));
@@ -302,7 +303,7 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
if (StringUtil.isEmptyOrSpaces(line)) {
continue;
}
curMinIndent = Math.min(curMinIndent, getIndent(line));
curMinIndent = Math.min(curMinIndent, PyIndentUtil.getLineIndentSize(line));
}
final int minIndent = curMinIndent;
final List<String> dedentedLines = ContainerUtil.map(workList, new Function<Substring, String>() {
@@ -49,7 +49,7 @@ public abstract class DocStringBuilder {
@NotNull
public String buildContent(int indent, boolean indentFirst) {
return buildContent(StringUtil.repeat(" ", indent), indentFirst);
return buildContent(StringUtil.repeatSymbol(' ', indent), indentFirst);
}
@NotNull
@@ -17,9 +17,9 @@ package com.jetbrains.python.documentation.docstrings;
import com.intellij.openapi.util.TextRange;
import com.jetbrains.python.documentation.DocStringLineParser;
import com.jetbrains.python.psi.PyIndentUtil;
import com.jetbrains.python.toolbox.Substring;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,43 +31,35 @@ import java.util.List;
public abstract class DocStringUpdater<T extends DocStringLineParser> {
protected final T myOriginalDocString;
private final StringBuilder myBuilder;
private final List<UpdateOperation> myUpdates = new ArrayList<UpdateOperation>();
protected final List<AddParameter> myAddParameterRequests = new ArrayList<AddParameter>();
protected final List<AddException> myAddExceptionRequest = new ArrayList<AddException>();
protected final List<AddReturnType> myAddReturnTypeRequests = new ArrayList<AddReturnType>();
private final List<Modification> myUpdates = new ArrayList<Modification>();
private final String myMinContentIndent;
public DocStringUpdater(@NotNull T docString) {
public DocStringUpdater(@NotNull T docString, @NotNull String minContentIndent) {
myBuilder = new StringBuilder(docString.getDocStringContent().getSuperString());
myOriginalDocString = docString;
myMinContentIndent = minContentIndent;
}
public final void addParameter(@NotNull String name, @Nullable String type) {
myAddParameterRequests.add(new AddParameter(name, type));
}
public final void addReturnType(@Nullable String name, @NotNull String type) {
myAddReturnTypeRequests.add(new AddReturnType(name, type));
}
public final void addException(@NotNull String type) {
myAddExceptionRequest.add(new AddException(type));
}
protected void insert(int offset, @NotNull String text) {
myUpdates.add(new UpdateOperation(TextRange.from(offset, 0), text));
}
protected final void insertAfterLine(int lineNumber, @NotNull String text) {
final Substring line = myOriginalDocString.getLines().get(lineNumber);
insert(line.getEndOffset(), "\n" + text);
protected final void replace(@NotNull TextRange range, @NotNull String text) {
myUpdates.add(new Modification(range, text));
}
protected final void replace(int startOffset, int endOffset, @NotNull String text) {
replace(new TextRange(startOffset, endOffset), text);
}
protected final void replace(@NotNull TextRange range, @NotNull String text) {
myUpdates.add(new UpdateOperation(range, text));
protected final void insert(int offset, @NotNull String text) {
replace(offset, offset, text);
}
protected final void insertAfterLine(int lineNumber, @NotNull String text) {
final Substring line = myOriginalDocString.getLines().get(lineNumber);
insert(line.getEndOffset(), '\n' + text);
}
protected final void insertBeforeLine(int lineNumber, @NotNull String text) {
final Substring line = myOriginalDocString.getLines().get(lineNumber);
insert(line.getStartOffset(), text + '\n');
}
protected abstract void scheduleUpdates();
@@ -75,11 +67,15 @@ public abstract class DocStringUpdater<T extends DocStringLineParser> {
@NotNull
public final String getDocStringText() {
scheduleUpdates();
// if several updates insert in one place (e.g. new field), insert them in backward order
// Move closing quotes to the next line, if new lines are going to be inserted
if (myOriginalDocString.getLineCount() == 1 && !myUpdates.isEmpty()) {
insertAfterLine(0, myMinContentIndent);
}
// If several updates insert in one place (e.g. new field), insert them in backward order,
// so the first added is placed above
Collections.reverse(myUpdates);
Collections.sort(myUpdates);
for (int i = myUpdates.size() - 1; i >= 0; i--) {
final UpdateOperation update = myUpdates.get(i);
Collections.sort(myUpdates, Collections.reverseOrder());
for (final Modification update : myUpdates) {
final TextRange updateRange = update.range;
if (updateRange.getStartOffset() == updateRange.getEndOffset()) {
myBuilder.insert(updateRange.getStartOffset(), update.text);
@@ -96,45 +92,26 @@ public abstract class DocStringUpdater<T extends DocStringLineParser> {
return myOriginalDocString;
}
protected static class AddParameter {
@NotNull final String name;
@Nullable final String type;
public AddParameter(@NotNull String name, @Nullable String type) {
this.name = name;
this.type = type;
@NotNull
protected String getLineIndent(int lastNonEmptyLine) {
final String indent = myOriginalDocString.getLineIndent(lastNonEmptyLine);
if (PyIndentUtil.getLineIndentSize(indent) < PyIndentUtil.getLineIndentSize(myMinContentIndent)) {
return myMinContentIndent;
}
return indent;
}
protected static class AddReturnType {
@Nullable final String name;
@NotNull final String type;
public AddReturnType(@Nullable String name, @NotNull String type) {
this.name = name;
this.type = type;
}
}
protected static class AddException {
@NotNull final String type;
public AddException(@NotNull String type) {
this.type = type;
}
}
private static class UpdateOperation implements Comparable<UpdateOperation> {
private static class Modification implements Comparable<Modification> {
@NotNull final TextRange range;
@NotNull final String text;
public UpdateOperation(@NotNull TextRange range, @NotNull String newText) {
public Modification(@NotNull TextRange range, @NotNull String newText) {
this.range = range;
this.text = newText;
}
@Override
public int compareTo(UpdateOperation o) {
public int compareTo(Modification o) {
return range.getStartOffset() - o.range.getStartOffset();
}
}
@@ -34,8 +34,7 @@ public class EpydocDocStringProvider extends DocStringProvider<EpydocString> {
@NotNull
@Override
public DocStringUpdater updateDocString(@NotNull EpydocString docstring) {
return new TagBasedDocStringUpdater<EpydocString>(docstring, TAG_PREFIX) {
@Override
return new TagBasedDocStringUpdater<EpydocString>(docstring, TAG_PREFIX, "") {
public DocStringBuilder createDocStringBuilder() {
return createDocString();
}
@@ -34,8 +34,7 @@ public class SphinxDocstringProvider extends DocStringProvider<SphinxDocString>{
@NotNull
@Override
public DocStringUpdater updateDocString(@NotNull SphinxDocString docstring) {
return new TagBasedDocStringUpdater<SphinxDocString>(docstring, TAG_PREFIX) {
@Override
return new TagBasedDocStringUpdater<SphinxDocString>(docstring, TAG_PREFIX, "") {
public DocStringBuilder createDocStringBuilder() {
return createDocString();
}
@@ -15,84 +15,79 @@
*/
package com.jetbrains.python.documentation.docstrings;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.documentation.TagBasedDocString;
import com.jetbrains.python.toolbox.Substring;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Mikhail Golubev
*/
public abstract class TagBasedDocStringUpdater<T extends TagBasedDocString> extends DocStringUpdater<T>{
public class TagBasedDocStringUpdater<T extends TagBasedDocString> extends DocStringUpdater<T>{
private final String myTagPrefix;
public TagBasedDocStringUpdater(@NotNull T docString, @NotNull String prefix) {
super(docString);
myTagPrefix = prefix;
public TagBasedDocStringUpdater(@NotNull T docString, @NotNull String tagPrefix, @NotNull String minContentIndent) {
super(docString, minContentIndent);
myTagPrefix = tagPrefix;
}
@NotNull
private TagBasedDocStringBuilder createBuilder() {
return new TagBasedDocStringBuilder(myTagPrefix);
}
@Override
protected void scheduleUpdates() {
final int anchorLine = firstLineWithTag();
final int anchorLineIndent = myOriginalDocString.getLineIndent(anchorLine);
for (AddParameter paramReq : myAddParameterRequests) {
if (!myOriginalDocString.getParameters().contains(paramReq.name)) {
insertAfterLine(anchorLine, createParameterNameLine(paramReq.name, anchorLineIndent));
}
if (paramReq.type != null) {
final Substring typeSub = myOriginalDocString.getParamTypeSubstring(paramReq.name);
if (typeSub != null) {
replace(typeSub.getTextRange(), paramReq.type);
}
else {
insertAfterLine(anchorLine, createParameterTypeLine(paramReq.name, paramReq.type, anchorLineIndent));
}
}
}
public final void addParameter(@NotNull String name, @Nullable String type) {
if (type != null) {
insertTagLine(createBuilder().addParameterType(name, type));
}
for (AddReturnType returnReq : myAddReturnTypeRequests) {
final Substring typeSub = myOriginalDocString.getReturnTypeSubstring();
if (typeSub != null) {
replace(typeSub.getTextRange(), returnReq.type);
}
else {
insertAfterLine(anchorLine, createReturnTypeLine(returnReq.type, anchorLineIndent));
}
}
for (AddException exception : myAddExceptionRequest) {
//TODO check existing docstring
insertAfterLine(anchorLine, createRaisesLine(exception.type, anchorLineIndent));
else {
insertTagLine(createBuilder().addParameterDescription(name, ""));
}
}
@NotNull
private String createRaisesLine(@NotNull String type, int indent) {
return ""; /*createDocStringBuilder().addException(type).buildContent(indent, true);*/
public final void addReturnValue(@Nullable String type) {
if (type != null) {
insertTagLine(createBuilder().addReturnValueType(type));
}
else {
insertTagLine(createBuilder().addReturnValueDescription(""));
}
}
@NotNull
private String createParameterNameLine(@NotNull String name, int indent) {
return ""; /*createDocStringBuilder().addParameter(name, null).buildContent(indent, true);*/
private void insertTagLine(@NotNull DocStringBuilder lineBuilder) {
final int firstLineWithTag = findFirstLineWithTag();
if (firstLineWithTag >= 0) {
final String indent = getLineIndent(firstLineWithTag);
insertBeforeLine(firstLineWithTag, lineBuilder.buildContent(indent, true));
return;
}
final int lastNonEmptyLine = findLastNonEmptyLine();
final String indent = getLineIndent(lastNonEmptyLine);
insertAfterLine(lastNonEmptyLine, lineBuilder.buildContent(indent, true));
}
@NotNull
private String createParameterTypeLine(@NotNull String name, @NotNull String type, int indent) {
return ""; /*createDocStringBuilder().addParameterType(name, type).buildContent(indent, true);*/
}
@NotNull
private String createReturnTypeLine(@NotNull String type, int indent) {
return ""; /*createDocStringBuilder().addReturnValue(null, type).buildContent(indent, true);*/
}
private int firstLineWithTag() {
for (int i = 0; i < myOriginalDocString.getLineCount(); i++) {
final Substring line = myOriginalDocString.getLine(i);
if (line.contains(myTagPrefix)) {
private int findLastNonEmptyLine() {
for (int i = myOriginalDocString.getLineCount() - 1; i >= 0; i--) {
if (StringUtil.isEmptyOrSpaces(myOriginalDocString.getLine(i))) {
return i;
}
}
return myOriginalDocString.getLineCount() - 1;
return 0;
}
public abstract DocStringBuilder createDocStringBuilder();
private int findFirstLineWithTag() {
for (int i = 0; i < myOriginalDocString.getLineCount(); i++) {
final Substring line = myOriginalDocString.getLine(i);
if (line.trimLeft().startsWith(myTagPrefix)) {
return i;
}
}
return -1;
}
}
@@ -42,7 +42,7 @@ public class PyIndentUtil {
int stop;
for (stop = 0; stop < line.length(); stop++) {
final char c = line.charAt(stop);
if (c == ' ' || c == '\t') {
if (!(c == ' ' || c == '\t')) {
break;
}
}
@@ -1,6 +1,6 @@
def func(x):
"""
:rtype: object
"""
return 1