From 17c24b9daf4ae08e6f477927d90801917ce3f4d8 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 18 Jan 2017 18:29:23 +0300 Subject: [PATCH] PY-20633 Options to put open/close parentheses in "from" imports on their own lines --- .../python/formatter/PyCodeStyleSettings.java | 2 ++ .../PyLanguageCodeStyleSettingsProvider.java | 7 +++++++ .../formatter/PythonFormattingModelBuilder.java | 13 ++++++++----- .../formatter/fromImportParenthesesPlacement.py | 11 +++++++++++ .../fromImportParenthesesPlacement_after.py | 17 +++++++++++++++++ ...g.py => fromImportWrappingChopDownIfLong.py} | 0 ...> fromImportWrappingChopDownIfLong_after.py} | 0 .../com/jetbrains/python/PyFormatterTest.java | 10 ++++++++++ 8 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 python/testData/formatter/fromImportParenthesesPlacement.py create mode 100644 python/testData/formatter/fromImportParenthesesPlacement_after.py rename python/testData/formatter/{fromImportsWrappingChopDownIfLong.py => fromImportWrappingChopDownIfLong.py} (100%) rename python/testData/formatter/{fromImportsWrappingChopDownIfLong_after.py => fromImportWrappingChopDownIfLong_after.py} (100%) diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java index e103352a5cd5..64ca601e0d03 100644 --- a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java +++ b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java @@ -97,6 +97,8 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings { * Affects wrapping of multiple imported names in a single "from" import. */ public int FROM_IMPORT_WRAPPING = WrapType.NORMAL.getLegacyRepresentation(); + public boolean FROM_IMPORT_NEW_LINE_AFTER_LEFT_PARENTHESIS = false; + public boolean FROM_IMPORT_NEW_LINE_BEFORE_RIGHT_PARENTHESIS = false; /** * Corresponds to the option of pycodestyle.py "--hang-closing". Basically, it means that the closing brace of a collection literal, diff --git a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java index 94c2037903e1..5e7ade520905 100644 --- a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java +++ b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java @@ -119,11 +119,18 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin consumer.showCustomOption(PyCodeStyleSettings.class, "ALIGN_COLLECTIONS_AND_COMPREHENSIONS", PyBundle.message("formatter.align.when.multiline"), PyBundle.message("formatter.collections.and.comprehensions")); + consumer.showCustomOption(PyCodeStyleSettings.class, "FROM_IMPORT_WRAPPING", PyBundle.message("formatter.from.import.statements"), null, WRAP_OPTIONS, WRAP_VALUES); consumer.showCustomOption(PyCodeStyleSettings.class, "ALIGN_MULTILINE_IMPORTS", PyBundle.message("formatter.align.when.multiline"), PyBundle.message("formatter.from.import.statements")); + consumer.showCustomOption(PyCodeStyleSettings.class, "FROM_IMPORT_NEW_LINE_AFTER_LEFT_PARENTHESIS", + ApplicationBundle.message("wrapping.new.line.after.lpar"), + PyBundle.message("formatter.from.import.statements")); + consumer.showCustomOption(PyCodeStyleSettings.class, "FROM_IMPORT_NEW_LINE_BEFORE_RIGHT_PARENTHESIS", + ApplicationBundle.message("wrapping.rpar.on.new.line"), + PyBundle.message("formatter.from.import.statements")); consumer.showCustomOption(PyCodeStyleSettings.class, "DICT_WRAPPING", PyBundle.message("formatter.dictionary.literals"), null, WRAP_OPTIONS, WRAP_VALUES); diff --git a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java index cf1a1d3dc06c..71100d5f408b 100644 --- a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java @@ -101,19 +101,23 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C .afterInside(RARROW, ANNOTATION).spaces(1) .between(allButLambda(), PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_METHOD_PARENTHESES) - - .betweenInside(COMMA, RBRACE, DICT_LITERAL_EXPRESSION).spaceIf(pySettings.SPACE_WITHIN_BRACES | commonSettings.SPACE_AFTER_COMMA, + + .betweenInside(COMMA, RBRACE, DICT_LITERAL_EXPRESSION).spaceIf(pySettings.SPACE_WITHIN_BRACES | commonSettings.SPACE_AFTER_COMMA, pySettings.DICT_NEW_LINE_BEFORE_RIGHT_BRACE) .afterInside(LBRACE, DICT_LITERAL_EXPRESSION).spaceIf(pySettings.SPACE_WITHIN_BRACES, pySettings.DICT_NEW_LINE_AFTER_LEFT_BRACE) .beforeInside(RBRACE, DICT_LITERAL_EXPRESSION).spaceIf(pySettings.SPACE_WITHIN_BRACES, pySettings.DICT_NEW_LINE_BEFORE_RIGHT_BRACE) .between(COMMA, RBRACE).spaceIf(pySettings.SPACE_WITHIN_BRACES | commonSettings.SPACE_AFTER_COMMA) .withinPair(LBRACE, RBRACE).spaceIf(pySettings.SPACE_WITHIN_BRACES) - + .between(COMMA, RBRACKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS | commonSettings.SPACE_AFTER_COMMA) .withinPair(LBRACKET, RBRACKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) - + .before(COLON).spaceIf(pySettings.SPACE_BEFORE_PY_COLON) + .afterInside(LPAR, FROM_IMPORT_STATEMENT).spaces(0, pySettings.FROM_IMPORT_NEW_LINE_AFTER_LEFT_PARENTHESIS) + .betweenInside(COMMA, RPAR, FROM_IMPORT_STATEMENT).spaceIf(commonSettings.SPACE_AFTER_COMMA, + pySettings.FROM_IMPORT_NEW_LINE_BEFORE_RIGHT_PARENTHESIS) + .beforeInside(RPAR, FROM_IMPORT_STATEMENT).spaces(0, pySettings.FROM_IMPORT_NEW_LINE_BEFORE_RIGHT_PARENTHESIS) .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA) .before(COMMA).spaceIf(commonSettings.SPACE_BEFORE_COMMA) .between(FROM_KEYWORD, DOT).spaces(1) @@ -125,7 +129,6 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C .withinPairInside(LPAR, RPAR, ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES) .betweenInside(LPAR, RPAR, PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_EMPTY_METHOD_PARENTHESES) .withinPairInside(LPAR, RPAR, PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES) - .withinPairInside(LPAR, RPAR, FROM_IMPORT_STATEMENT).spaces(0) .withinPairInside(LPAR, RPAR, GENERATOR_EXPRESSION).spaces(0) .withinPairInside(LPAR, RPAR, PARENTHESIZED_EXPRESSION).spaces(0) .before(LBRACKET).spaceIf(pySettings.SPACE_BEFORE_LBRACKET) diff --git a/python/testData/formatter/fromImportParenthesesPlacement.py b/python/testData/formatter/fromImportParenthesesPlacement.py new file mode 100644 index 000000000000..fb69478bd4e4 --- /dev/null +++ b/python/testData/formatter/fromImportParenthesesPlacement.py @@ -0,0 +1,11 @@ +from module import (foo, bar) +from module import (foo, bar,) +from module import (foo, bar, baz, quux) +from module import (foo, + bar) +from module import (foo, + bar, + ) +from module import ( + foo, + bar) \ No newline at end of file diff --git a/python/testData/formatter/fromImportParenthesesPlacement_after.py b/python/testData/formatter/fromImportParenthesesPlacement_after.py new file mode 100644 index 000000000000..fbf0e7a00dc0 --- /dev/null +++ b/python/testData/formatter/fromImportParenthesesPlacement_after.py @@ -0,0 +1,17 @@ +from module import (foo, bar) +from module import (foo, bar, ) +from module import ( + foo, bar, baz, quux + ) +from module import ( + foo, + bar + ) +from module import ( + foo, + bar, + ) +from module import ( + foo, + bar +) diff --git a/python/testData/formatter/fromImportsWrappingChopDownIfLong.py b/python/testData/formatter/fromImportWrappingChopDownIfLong.py similarity index 100% rename from python/testData/formatter/fromImportsWrappingChopDownIfLong.py rename to python/testData/formatter/fromImportWrappingChopDownIfLong.py diff --git a/python/testData/formatter/fromImportsWrappingChopDownIfLong_after.py b/python/testData/formatter/fromImportWrappingChopDownIfLong_after.py similarity index 100% rename from python/testData/formatter/fromImportsWrappingChopDownIfLong_after.py rename to python/testData/formatter/fromImportWrappingChopDownIfLong_after.py diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java index 551b5297ca12..8843ae87bb97 100644 --- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java +++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java @@ -740,6 +740,16 @@ public class PyFormatterTest extends PyTestCase { doTest(); } + // PY-20633 + // XXX causes jumping closing parenthesis, because of the hanging indent detection + public void testFromImportParenthesesPlacement() { + getPythonCodeStyleSettings().FROM_IMPORT_NEW_LINE_AFTER_LEFT_PARENTHESIS = true; + getPythonCodeStyleSettings().FROM_IMPORT_NEW_LINE_BEFORE_RIGHT_PARENTHESIS = true; + getCommonCodeStyleSettings().SPACE_AFTER_COLON = true; + getCodeStyleSettings().setRightMargin(PythonLanguage.INSTANCE, 35); + doTest(); + } + public void testVariableAnnotations() { runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest); }