if (SectionBasedDocString.isValidSectionTitle(header)) {
final String patch = (trimmedLine.endsWith(":") ? "\n" : ":\n") +
PyIndentUtil.getLineIndent(line) +
- GoogleCodeStyleDocStringBuilder.DEFAULT_SECTION_INDENT;
+ GoogleCodeStyleDocStringBuilder.getDefaultSectionIndent(pyString.getProject());
final int insertionOffset = lineStart + StringUtil.trimTrailing(line).length();
document.replaceString(insertionOffset, lineEnd, patch);
processor.registerUnresolvedError(insertionOffset + patch.length());
if (name.isEmpty()) return;
PyExpression body = lambdaExpression.getBody();
- PyFunctionBuilder functionBuilder = new PyFunctionBuilder(name);
+ PyFunctionBuilder functionBuilder = new PyFunctionBuilder(name, lambdaExpression);
for (PyParameter param : lambdaExpression.getParameterList().getParameters()) {
functionBuilder.parameter(param.getText());
}
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyFunctionBuilder;
import com.jetbrains.python.psi.impl.PyPsiUtils;
-import com.jetbrains.python.psi.types.*;
+import com.jetbrains.python.psi.types.PyClassLikeType;
+import com.jetbrains.python.psi.types.PyClassLikeTypeUtil;
+import com.jetbrains.python.psi.types.PyNoneType;
+import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass, PyFunction baseFunction, boolean implement) {
final boolean overridingNew = PyNames.NEW.equals(baseFunction.getName());
- PyFunctionBuilder pyFunctionBuilder = new PyFunctionBuilder(baseFunction.getName());
+ PyFunctionBuilder pyFunctionBuilder = new PyFunctionBuilder(baseFunction.getName(), baseFunction);
final PyDecoratorList decorators = baseFunction.getDecoratorList();
boolean baseMethodIsStatic = false;
if (decorators != null) {
*/
package com.jetbrains.python.documentation.docstrings;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
+import com.jetbrains.python.psi.PyIndentUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
* @author Mikhail Golubev
*/
public class GoogleCodeStyleDocStringBuilder extends SectionBasedDocStringBuilder {
- public static final String DEFAULT_SECTION_INDENT = " ";
- public static final String DEFAULT_CONTINUATION_INDENT = " ";
+ public static final String DEFAULT_CONTINUATION_INDENT = PyIndentUtil.FOUR_SPACES;
- public GoogleCodeStyleDocStringBuilder() {
- // Two spaces according to Google Code Style
- super(DEFAULT_SECTION_INDENT, DEFAULT_CONTINUATION_INDENT);
+ @NotNull
+ public static String getDefaultSectionIndent(@NotNull Project project) {
+ return PyIndentUtil.getIndentFromSettings(project);
+ }
+
+ @NotNull
+ public static GoogleCodeStyleDocStringBuilder forProject(@NotNull Project project) {
+ return new GoogleCodeStyleDocStringBuilder(getDefaultSectionIndent(project));
+ }
+
+ public GoogleCodeStyleDocStringBuilder(@NotNull String sectionIndent) {
+ super(sectionIndent, DEFAULT_CONTINUATION_INDENT);
}
@Override
*/
package com.jetbrains.python.documentation.docstrings;
+import com.intellij.openapi.project.Project;
import com.jetbrains.python.toolbox.Substring;
import org.jetbrains.annotations.NotNull;
* @author Mikhail Golubev
*/
public class GoogleCodeStyleDocStringUpdater extends SectionBasedDocStringUpdater {
- public GoogleCodeStyleDocStringUpdater(@NotNull SectionBasedDocString docString, @NotNull String minContentIndent) {
+ private final String myFallbackSectionIndent;
+
+ public static GoogleCodeStyleDocStringUpdater forProject(@NotNull GoogleCodeStyleDocString docString,
+ @NotNull String minContentIndent,
+ @NotNull Project project) {
+ return new GoogleCodeStyleDocStringUpdater(docString, minContentIndent, GoogleCodeStyleDocStringBuilder.getDefaultSectionIndent(project));
+ }
+
+ public GoogleCodeStyleDocStringUpdater(@NotNull GoogleCodeStyleDocString docString,
+ @NotNull String minContentIndent,
+ @NotNull String fallbackSectionIndent) {
super(docString, minContentIndent);
+ myFallbackSectionIndent = fallbackSectionIndent;
}
@Override
insert(nameSubstring.getEndOffset(), " (" + type + ")");
}
+ @NotNull
@Override
protected SectionBasedDocStringBuilder createBuilder() {
- return new GoogleCodeStyleDocStringBuilder();
+ return new GoogleCodeStyleDocStringBuilder(myFallbackSectionIndent);
}
}
return getSectionStartLine(section) + 1;
}
+ @NotNull
@Override
protected SectionBasedDocStringBuilder createBuilder() {
return new NumpyDocStringBuilder();
private final List<DocstringParam> myAddedParams = Lists.newArrayList();
private final List<DocstringParam> myRemovedParams = Lists.newArrayList();
private final String myDocStringText;
-
// Updated after buildAndInsert()
@Nullable private PyDocStringOwner myDocStringOwner;
- private String myDocStringIndent;
- private DocStringFormat myDocStringFormat;
+ private final String myDocStringIndent;
+ private final DocStringFormat myDocStringFormat;
+ private final PsiElement mySettingsAnchor;
private boolean myUseTypesFromDebuggerSignature = true;
private boolean myNewMode = false; // true - generate new string, false - update existing
private PyDocstringGenerator(@Nullable PyDocStringOwner docStringOwner,
@Nullable String docStringText,
@NotNull DocStringFormat format,
- @NotNull String indentation) {
+ @NotNull String indentation,
+ @NotNull PsiElement settingsAnchor) {
myDocStringOwner = docStringOwner;
myDocStringIndent = indentation;
myDocStringFormat = format;
myDocStringText = docStringText;
myNewMode = myDocStringText == null;
+ mySettingsAnchor = settingsAnchor;
}
@NotNull
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)owner).getStatementList());
}
final String docStringText = owner.getDocStringExpression() == null ? null : owner.getDocStringExpression().getText();
- return new PyDocstringGenerator(owner, docStringText, DocStringUtil.getConfiguredDocStringFormat(owner), indentation);
+ return new PyDocstringGenerator(owner, docStringText, DocStringUtil.getConfiguredDocStringFormat(owner), indentation, owner);
}
@NotNull
- public static PyDocstringGenerator create(@NotNull DocStringFormat format, @NotNull String indentation) {
- return new PyDocstringGenerator(null, null, format, indentation);
+ public static PyDocstringGenerator create(@NotNull DocStringFormat format, @NotNull String indentation, @NotNull PsiElement settingsAnchor) {
+ return new PyDocstringGenerator(null, null, format, indentation, settingsAnchor);
}
@NotNull
public static PyDocstringGenerator update(@NotNull PyStringLiteralExpression docString) {
return new PyDocstringGenerator(PsiTreeUtil.getParentOfType(docString, PyDocStringOwner.class),
- docString.getText(), DocStringUtil.getConfiguredDocStringFormat(docString),
- PyIndentUtil.getElementIndent(docString));
+ docString.getText(),
+ DocStringUtil.getConfiguredDocStringFormat(docString),
+ PyIndentUtil.getElementIndent(docString),
+ docString);
}
@NotNull
public static PyDocstringGenerator update(@NotNull DocStringFormat format,
@NotNull String indentation,
- @NotNull String text) {
- return new PyDocstringGenerator(null, text, format, indentation);
+ @NotNull String text, PsiElement settingsAnchor) {
+ return new PyDocstringGenerator(null, text, format, indentation, settingsAnchor);
}
@NotNull
return myDocStringIndent;
}
- public void setDocStringFormat(@NotNull DocStringFormat format) {
- myDocStringFormat = format;
- }
-
@NotNull
public DocStringFormat getDocStringFormat() {
return myDocStringFormat;
}
- public void setDocStringIndent(@NotNull String docStringIndent) {
- myDocStringIndent = docStringIndent;
- }
-
public boolean isNewMode() {
return myNewMode;
}
}
}
else if (myDocStringFormat == DocStringFormat.GOOGLE || myDocStringFormat == DocStringFormat.NUMPY) {
- builder = myDocStringFormat == DocStringFormat.GOOGLE ? new GoogleCodeStyleDocStringBuilder() : new NumpyDocStringBuilder();
+ builder = myDocStringFormat == DocStringFormat.GOOGLE ? GoogleCodeStyleDocStringBuilder.forProject(mySettingsAnchor.getProject()) : new NumpyDocStringBuilder();
final SectionBasedDocStringBuilder sectionBuilder = (SectionBasedDocStringBuilder)builder;
if (myAddFirstEmptyLine) {
sectionBuilder.addEmptyLine();
}
else if (myDocStringFormat == DocStringFormat.GOOGLE) {
//noinspection ConstantConditions
- updater = new GoogleCodeStyleDocStringUpdater((SectionBasedDocString)getStructuredDocString(), myDocStringIndent);
+ updater = GoogleCodeStyleDocStringUpdater.forProject((GoogleCodeStyleDocString)getStructuredDocString(),
+ myDocStringIndent,
+ mySettingsAnchor.getProject());
}
else if (myDocStringFormat == DocStringFormat.NUMPY) {
//noinspection ConstantConditions
protected abstract void updateParamDeclarationWithType(@NotNull Substring nameSubstring, @NotNull String type);
+ @NotNull
protected abstract SectionBasedDocStringBuilder createBuilder();
@Nullable
final TextRange lineRange = TextRange.create(document.getLineStartOffset(lineNum - 1), document.getLineEndOffset(lineNum - 1));
final Matcher matcher = GoogleCodeStyleDocString.SECTION_HEADER.matcher(document.getText(lineRange));
if (matcher.matches() && SectionBasedDocString.isValidSectionTitle(matcher.group(1))) {
- document.insertString(offset, GoogleCodeStyleDocStringBuilder.DEFAULT_SECTION_INDENT);
+ document.insertString(offset, GoogleCodeStyleDocStringBuilder.getDefaultSectionIndent(file.getProject()));
editor.getCaretModel().moveCaretRelatively(2, 0, false, false, false);
}
}
sure(FileModificationService.getInstance().preparePsiElementForWrite(file));
// try to at least match parameter count
// TODO: get parameter style from code style
- PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier);
+ PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier, problemElement);
PsiElement problemParent = problemElement.getParent();
if (problemParent instanceof PyCallExpression) {
PyArgumentList arglist = ((PyCallExpression)problemParent).getArgumentList();
sure(FileModificationService.getInstance().preparePsiElementForWrite(clsStmtList));
// try to at least match parameter count
// TODO: get parameter style from code style
- PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier);
+ PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier, cls);
PsiElement pe = problemElement.getParent();
String decoratorName = null; // set to non-null to add a decorator
PyExpression[] args = new PyExpression[0];
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
if (!myElement.isValid() || !FileModificationService.getInstance().preparePsiElementForWrite(myElement)) return;
- PyFunctionBuilder functionBuilder = new PyFunctionBuilder(myReference.getText());
+ PyFunctionBuilder functionBuilder = new PyFunctionBuilder(myReference.getText(), myElement);
// if function is actually an argument of a call, don't use other arguments of the call to create parameter list of new function
final PyArgumentList argumentList = myElement.getArgumentList();
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PythonFileType;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
* @author Mikhail Golubev
*/
public class PyIndentUtil {
+ @NonNls public static final String TWO_SPACES = " ";
+ @NonNls public static final String FOUR_SPACES = " ";
+
private PyIndentUtil() {
}
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.documentation.docstrings.DocStringFormat;
+import com.jetbrains.python.documentation.docstrings.DocStringUtil;
import com.jetbrains.python.documentation.docstrings.PyDocstringGenerator;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@NotNull
private final Map<String, String> myDecoratorValues = new HashMap<String, String>();
private boolean myAsync = false;
- private PyDocstringGenerator myDocStringGenerator = PyDocstringGenerator.create(DocStringFormat.REST, " ");
+ private PyDocstringGenerator myDocStringGenerator;
/**
* Creates builder copying signature and doc from another one.
@NotNull
public static PyFunctionBuilder copySignature(@NotNull final PyFunction source, @NotNull final String... decoratorsToCopyIfExist) {
final String name = source.getName();
- final PyFunctionBuilder functionBuilder = new PyFunctionBuilder((name != null) ? name : "");
+ final PyFunctionBuilder functionBuilder = new PyFunctionBuilder((name != null) ? name : "", source);
for (final PyParameter parameter : source.getParameterList().getParameters()) {
final String parameterName = parameter.getName();
if (parameterName != null) {
return functionBuilder;
}
- public PyFunctionBuilder(@NotNull String name) {
+ public PyFunctionBuilder(@NotNull String name, @NotNull PsiElement settingsAnchor) {
myName = name;
+ myDocStringGenerator = PyDocstringGenerator.create(DocStringUtil.getConfiguredDocStringFormat(settingsAnchor),
+ PyIndentUtil.getIndentFromSettings(settingsAnchor.getProject()),
+ settingsAnchor);
}
/**
* Adds param and its type to doc
+ * @param format what docstyle to use to doc param type
* @param name param name
* @param type param type
- * @param format what docstyle to use to doc param type
*/
@NotNull
- public PyFunctionBuilder parameterWithType(@NotNull final String name,
- @NotNull final String type,
- @NotNull final DocStringFormat format) {
+ public PyFunctionBuilder parameterWithType(@NotNull String name, @NotNull String type) {
parameter(name);
- myDocStringGenerator.setDocStringFormat(format);
myDocStringGenerator.withParamTypedByName(name, type);
return this;
}
List<String> statements = myStatements.isEmpty() ? Collections.singletonList(PyNames.PASS) : myStatements;
final String indent = PyIndentUtil.getIndentFromSettings(project);
- myDocStringGenerator.setDocStringIndent(indent);
// There was original docstring or some parameters were added via parameterWithType()
if (!myDocStringGenerator.isNewMode() || myDocStringGenerator.hasParametersToAdd()) {
final String docstring = PyIndentUtil.changeIndent(myDocStringGenerator.buildDocString(), true, indent);
//TODO: Move to utils?
@NotNull
private static PyFunction createInitMethod(@NotNull final PyClass to) {
- final PyFunctionBuilder functionBuilder = new PyFunctionBuilder(PyNames.INIT);
+ final PyFunctionBuilder functionBuilder = new PyFunctionBuilder(PyNames.INIT, to);
functionBuilder.parameter(PyNames.CANONICAL_SELF); //TODO: Take param from codestyle?
final PyFunction function = functionBuilder.buildFunction(to.getProject(), LanguageLevel.forElement(to));
return PyClassRefactoringUtil.addMethods(to, true, function).get(0);
}
}
// Change signature according to pass settings and
- final PyFunctionBuilder builder = new PyFunctionBuilder("foo");
+ final PyFunctionBuilder builder = new PyFunctionBuilder("foo", generatedMethod);
if (isClassMethod) {
builder.parameter("cls");
}
@NotNull final AbstractVariableData[] variableData,
@NotNull final PsiElement expression,
@Nullable final PyUtil.MethodFlags flags, boolean isAsync) {
- final PyFunctionBuilder builder = new PyFunctionBuilder(methodName);
+ final PyFunctionBuilder builder = new PyFunctionBuilder(methodName, expression);
addDecorators(builder, flags);
addFakeParameters(builder, variableData);
if (isAsync) {
boolean isAsync) {
assert !elementsRange.isEmpty() : "Empty statements list was selected!";
- final PyFunctionBuilder builder = new PyFunctionBuilder(methodName);
+ final PyFunctionBuilder builder = new PyFunctionBuilder(methodName, elementsRange.get(0));
if (isAsync) {
builder.makeAsync();
}
if (init != null) {
return AddFieldQuickFix.appendToMethod(init, callback);
}
- final PyFunctionBuilder builder = new PyFunctionBuilder(PythonUnitTestUtil.TESTCASE_SETUP_NAME);
+ final PyFunctionBuilder builder = new PyFunctionBuilder(PythonUnitTestUtil.TESTCASE_SETUP_NAME, clazz);
builder.parameter(PyNames.CANONICAL_SELF);
PyFunction setUp = builder.buildFunction(clazz.getProject(), LanguageLevel.getDefault());
final PyStatementList statements = clazz.getStatementList();
def func():
"""
Args:
- <caret>
+ <caret>
"""
\ No newline at end of file
--- /dev/null
+def f():
+ """
+ Raises:<caret>
+ """
\ No newline at end of file
--- /dev/null
+def f():
+ """
+ Raises:
+ <caret>
+ """
\ No newline at end of file
def f():
"""
Raises:
- <caret>
+ <caret>
"""
\ No newline at end of file
def f(param):
"""
Args:
- param
+ param
"""
\ No newline at end of file
--- /dev/null
+def f(param):
+ """
+ Args:
+ param<caret>
+ """
\ No newline at end of file
--- /dev/null
+def f(param):
+ """
+ Args:<caret>
+ """
\ No newline at end of file
def f(**kwargs):
"""
Args:
- **kwargs:
+ **kwargs:
"""
\ No newline at end of file
def f(b):
"""
Args:
- b:
+ b:
"""
\ No newline at end of file
def f(*args):
"""
Args:
- *args:
+ *args:
"""
\ No newline at end of file
def f(x, y, z):
"""
Parameters:
- x:
- y:
- z:
+ x:
+ y:
+ z:
"""
\ No newline at end of file
--- /dev/null
+def f(x, y, z):
+ """
+ Parameters:
+ x:
+ y:
+ z:
+ """
\ No newline at end of file
def f(x, y, z):
"""
Args:
- x:
- y:
- z:
+ x:
+ y:
+ z:
"""
\ No newline at end of file
--- /dev/null
+def f(x, y, z):
+ """
+ Args:
+ x:
+ y:
+ z:
+ """
\ No newline at end of file
--- /dev/null
+def f(x, y):
+ """
+
+ Args:
+ x:
+ y:
+
+ Returns:
+
+ """
+ return 42
\ No newline at end of file
"""
Args:
- x:
- y:
+ x:
+ y:
"""
"""
Args:
- x:
- y:
+ x:
+ y:
Returns:
"""
Args:
- x:
- y:
+ x:
+ y:
Returns:
"""
Args:
- x:
- y:
+ x:
+ y:
Returns:
"""
Args:
- x ():
- y ():
+ x ():
+ y ():
Returns:
def f(x, y):
"""
Args:
- x (object):
+ x (object):
"""
\ No newline at end of file
Summary.
Parameters:
- x (object):
+ x (object):
"""
\ No newline at end of file
Summary.
Args:
- x (object):
+ x (object):
"""
\ No newline at end of file
"""Summary.
Args:
- x (object):
+ x (object):
"""
\ No newline at end of file
"""
Args:
- x (object):
+ x (object):
"""
return 42
\ No newline at end of file
def f(x, y):
"""
Returns:
- object:
+ object:
"""
\ No newline at end of file
Summary.
Returns:
- object:
+ object:
"""
\ No newline at end of file
"""
Returns:
- object:
+ object:
"""
return 42
\ No newline at end of file
--- /dev/null
+def <caret>f(x, y, z):
+ """
+ Parameters:
+ """
\ No newline at end of file
--- /dev/null
+def <caret>f(x, y, z):
+ """
+ """
\ No newline at end of file
--- /dev/null
+def <caret>f(x, y):
+ return 42
\ No newline at end of file
doDocStringTypingTest("\nparam", DocStringFormat.GOOGLE);
}
+ // PY-16765
+ public void testSectionIndentInsideGoogleDocStringCustomIndent() {
+ getCommonCodeStyleSettings().getIndentOptions().INDENT_SIZE = 2;
+ doDocStringTypingTest("\nparam", DocStringFormat.GOOGLE);
+ }
+
public void testEnterInString() { // PY-1738
doTestEnter("a = \"some <caret>string\"", "a = \"some \" \\\n" +
" \"string\"");
}
});
}
+
+ // PY-16765
+ public void testGoogleDocStringIndentAfterSectionCustomIndent() {
+ getCommonCodeStyleSettings().getIndentOptions().INDENT_SIZE = 2;
+ runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {
+ public void run() {
+ doTest();
+ }
+ });
+ }
}
});
}
+ // PY-16765
+ public void testGoogleDocStubCustomIndent() {
+ getCommonCodeStyleSettings().getIndentOptions().INDENT_SIZE = 2;
+ doDocStubTest(DocStringFormat.GOOGLE);
+ }
+
// PY-9795
public void testGoogleDocStubInlineFunctionBody() {
doDocStubTest(DocStringFormat.GOOGLE);
doDocAddMissingParamsTest(DocStringFormat.GOOGLE);
}
+ // PY-16765
+ public void testAddMissingParamsInGoogleDocStringNoParamSectionCustomCodeIndent() {
+ getCommonCodeStyleSettings().getIndentOptions().INDENT_SIZE = 2;
+ doDocAddMissingParamsTest(DocStringFormat.GOOGLE);
+ }
+
// PY-9795
public void testAddMissingParamsInGoogleDocStringEmptyParamSection() {
doDocAddMissingParamsTest(DocStringFormat.GOOGLE);
}
+
+ // PY-16765
+ public void testAddMissingParamsInGoogleDocStringEmptyParamSectionCustomCodeIndent() {
+ getCommonCodeStyleSettings().getIndentOptions().INDENT_SIZE = 2;
+ doDocAddMissingParamsTest(DocStringFormat.GOOGLE);
+ }
// PY-4717
public void testReturnTypeInNewNumpyDocString() {