diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties
index 5d3b8e39e3d2..bd58902cc137 100644
--- a/python/pluginResources/messages/PyBundle.properties
+++ b/python/pluginResources/messages/PyBundle.properties
@@ -551,6 +551,7 @@ formatter.panel.dict.alignment.label=Dict alignment:
formatter.panel.add.trailing.line.feed=Add line feed at the end of file
formatter.panel.use.continuation.indent.for.title=Use continuation indent for
+formatter.panel.use.continuation.indent.for.parameters=Method declaration parameters
formatter.panel.use.continuation.indent.for.arguments=Method call arguments
formatter.panel.use.continuation.indent.for.collection.literals=Collections and comprehensions
diff --git a/python/python-psi-impl/src/com/jetbrains/python/formatter/PyBlock.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyBlock.java
index 355f306a04ac..f258260f683c 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/formatter/PyBlock.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyBlock.java
@@ -358,8 +358,8 @@ public class PyBlock implements ASTBlock {
if (childType == PyTokenTypes.RPAR && !settings.HANG_CLOSING_BRACKETS) {
childIndent = Indent.getNoneIndent();
}
- else if (parentType == PyElementTypes.PARAMETER_LIST ||
- settings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS ||
+ else if ((parentType == PyElementTypes.PARAMETER_LIST && settings.USE_CONTINUATION_INDENT_FOR_PARAMETERS) ||
+ (parentType == PyElementTypes.ARGUMENT_LIST && settings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS) ||
argumentMayHaveSameIndentAsFollowingStatementList()) {
childIndent = Indent.getContinuationIndent();
}
@@ -1074,7 +1074,7 @@ public class PyBlock implements ASTBlock {
final IElementType parentType = myNode.getElementType();
// constructs that imply indent for their children
final PyCodeStyleSettings settings = myContext.getPySettings();
- if (parentType == PyElementTypes.PARAMETER_LIST ||
+ if ((parentType == PyElementTypes.PARAMETER_LIST && settings.USE_CONTINUATION_INDENT_FOR_PARAMETERS) ||
(parentType == PyElementTypes.ARGUMENT_LIST && settings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS)) {
return Indent.getContinuationIndent();
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
index 24a56b104cf4..9763e524dfb6 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
@@ -80,6 +80,7 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings {
* (as long as they're multiple of 4), though examples in PEP 8 itself use mostly normal indent. Nonetheless, some users prefer to have
* the same indentation level for arguments as for parameters.
*/
+ public boolean USE_CONTINUATION_INDENT_FOR_PARAMETERS = true;
public boolean USE_CONTINUATION_INDENT_FOR_ARGUMENTS = false;
public boolean USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS = false;
diff --git a/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.form b/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.form
index ede28b676db3..05ae9466beea 100644
--- a/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.form
+++ b/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.form
@@ -53,7 +53,7 @@
-
+
@@ -72,9 +72,17 @@
+
+
+
+
+
+
+
+
-
+
diff --git a/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.java b/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.java
index b573ef8b1fba..3bc426859f7c 100644
--- a/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.java
+++ b/python/src/com/jetbrains/python/formatter/PyOtherCodeStylePanel.java
@@ -43,6 +43,7 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
private JPanel myPanel;
private JBCheckBox myAddTrailingBlankLineCheckbox;
+ private JBCheckBox myUseContinuationIndentForParameters;
private JBCheckBox myUseContinuationIndentForArguments;
private JBCheckBox myUseContinuationIndentForCollectionsAndComprehensions;
private ComboBox myDictAlignmentCombo;
@@ -74,6 +75,13 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
}
});
+ myUseContinuationIndentForParameters.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ somethingChanged();
+ }
+ });
+
myUseContinuationIndentForArguments.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -113,6 +121,7 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
}
}
myAddTrailingBlankLineCheckbox.setSelected(pySettings.BLANK_LINE_AT_FILE_END);
+ myUseContinuationIndentForParameters.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS);
myUseContinuationIndentForArguments.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS);
myUseContinuationIndentForCollectionsAndComprehensions.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS);
}
@@ -122,6 +131,7 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
final PyCodeStyleSettings customSettings = getCustomSettings(settings);
customSettings.DICT_ALIGNMENT = getDictAlignmentAsInt();
customSettings.BLANK_LINE_AT_FILE_END = ensureTrailingBlankLine();
+ customSettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS = useContinuationIndentForParameters();
customSettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS = useContinuationIndentForArguments();
customSettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS = useContinuationIndentForCollectionLiterals();
}
@@ -131,6 +141,7 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
final PyCodeStyleSettings customSettings = getCustomSettings(settings);
return customSettings.DICT_ALIGNMENT != getDictAlignmentAsInt() ||
customSettings.BLANK_LINE_AT_FILE_END != ensureTrailingBlankLine() ||
+ customSettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS != useContinuationIndentForParameters() ||
customSettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS != useContinuationIndentForArguments() ||
customSettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS != useContinuationIndentForCollectionLiterals();
}
@@ -153,6 +164,10 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
return myAddTrailingBlankLineCheckbox.isSelected();
}
+ private boolean useContinuationIndentForParameters() {
+ return myUseContinuationIndentForParameters.isSelected();
+ }
+
private boolean useContinuationIndentForArguments() {
return myUseContinuationIndentForArguments.isSelected();
}
@@ -166,6 +181,12 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
" 2,\n" +
" 3)\n" +
"\n" +
+ "def foo_decl(\n" +
+ " a,\n" +
+ " b,\n" +
+ " c):\n" +
+ " pass\n" +
+ "\n" +
"{\n" +
" \"green\": 42,\n" +
" \"eggs and ham\": -0.0e0\n" +
diff --git a/python/testData/formatter/continuationIndentBeforeFunctionParameters.py b/python/testData/formatter/continuationIndentBeforeFunctionParameters.py
new file mode 100644
index 000000000000..25e306b2663f
--- /dev/null
+++ b/python/testData/formatter/continuationIndentBeforeFunctionParameters.py
@@ -0,0 +1,12 @@
+def foo_decl1(
+ a,
+ b, c,
+d,
+):
+ pass
+
+def foo_decl2(
+a,
+ b, c,
+ d):
+ pass
diff --git a/python/testData/formatter/continuationIndentBeforeFunctionParameters_after.py b/python/testData/formatter/continuationIndentBeforeFunctionParameters_after.py
new file mode 100644
index 000000000000..9e5ab6bfe0fe
--- /dev/null
+++ b/python/testData/formatter/continuationIndentBeforeFunctionParameters_after.py
@@ -0,0 +1,13 @@
+def foo_decl1(
+ a,
+ b, c,
+ d,
+):
+ pass
+
+
+def foo_decl2(
+ a,
+ b, c,
+ d):
+ pass
diff --git a/python/testData/formatter/noContinuationIndentBeforeFunctionParameters.py b/python/testData/formatter/noContinuationIndentBeforeFunctionParameters.py
new file mode 100644
index 000000000000..25e306b2663f
--- /dev/null
+++ b/python/testData/formatter/noContinuationIndentBeforeFunctionParameters.py
@@ -0,0 +1,12 @@
+def foo_decl1(
+ a,
+ b, c,
+d,
+):
+ pass
+
+def foo_decl2(
+a,
+ b, c,
+ d):
+ pass
diff --git a/python/testData/formatter/noContinuationIndentBeforeFunctionParameters_after.py b/python/testData/formatter/noContinuationIndentBeforeFunctionParameters_after.py
new file mode 100644
index 000000000000..a8e0ac26533f
--- /dev/null
+++ b/python/testData/formatter/noContinuationIndentBeforeFunctionParameters_after.py
@@ -0,0 +1,13 @@
+def foo_decl1(
+ a,
+ b, c,
+ d,
+):
+ pass
+
+
+def foo_decl2(
+ a,
+ b, c,
+ d):
+ pass
diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
index 122b975da663..512bcef93e6a 100644
--- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java
+++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
@@ -660,6 +660,17 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
+ // PY-33060
+ public void testContinuationIndentBeforeFunctionParameters() {
+ doTest();
+ }
+
+ // PY-33060
+ public void testNoContinuationIndentBeforeFunctionParameters() {
+ getPythonCodeStyleSettings().USE_CONTINUATION_INDENT_FOR_PARAMETERS = false;
+ doTest();
+ }
+
// PY-17979, PY-13304
public void testContinuationIndentBeforeFunctionArguments() {
getPythonCodeStyleSettings().USE_CONTINUATION_INDENT_FOR_ARGUMENTS = true;