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;