From 4db90932c04ab7c6846fe82bcc5346aff7b36a0e Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Thu, 23 Jan 2014 22:12:30 +0100 Subject: [PATCH] Fix align multiline elements in parenthesized expressions, parameters and arguments lists. --- .../jetbrains/python/formatter/PyBlock.java | 62 +++++++++++++++---- .../formatter/alignInCallExpression.py | 3 + .../formatter/alignInCallExpression_after.py | 3 + .../formatter/alignInParameterList.py | 4 ++ .../formatter/alignInParameterList_after.py | 4 ++ .../alignInParenthesizedExpression.py | 8 +++ .../alignInParenthesizedExpression_after.py | 8 +++ python/testData/formatter/wrapOnDot_after.py | 2 +- .../com/jetbrains/python/PyFormatterTest.java | 14 ++++- 9 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 python/testData/formatter/alignInCallExpression.py create mode 100644 python/testData/formatter/alignInCallExpression_after.py create mode 100644 python/testData/formatter/alignInParameterList.py create mode 100644 python/testData/formatter/alignInParameterList_after.py create mode 100644 python/testData/formatter/alignInParenthesizedExpression.py create mode 100644 python/testData/formatter/alignInParenthesizedExpression_after.py diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 8d76da821c9b..d160749fbda8 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -191,16 +191,6 @@ public class PyBlock implements ASTBlock { childIndent = Indent.getNormalIndent(); } } - else if (parentType == PyElementTypes.ARGUMENT_LIST || parentType == PyElementTypes.PARAMETER_LIST) { - if (childType == PyTokenTypes.RPAR) { - childIndent = Indent.getNoneIndent(); - } - else { - childIndent = parentType == PyElementTypes.PARAMETER_LIST || isInControlStatement() - ? Indent.getContinuationIndent() - : Indent.getNormalIndent(/*true*/); - } - } else if (parentType == PyElementTypes.DICT_LITERAL_EXPRESSION || parentType == PyElementTypes.SET_LITERAL_EXPRESSION || parentType == PyElementTypes.SET_COMP_EXPRESSION || parentType == PyElementTypes.DICT_COMP_EXPRESSION) { if (childType == PyTokenTypes.RBRACE || !hasLineBreaksBefore(child, 1)) { @@ -236,7 +226,25 @@ public class PyBlock implements ASTBlock { childIndent = Indent.getNormalIndent(); } } - else if (parentType == PyElementTypes.PARENTHESIZED_EXPRESSION || parentType == PyElementTypes.GENERATOR_EXPRESSION) { + //Align elements vertically if there is an argument in the first line of parenthesized expression + else if (((parentType == PyElementTypes.PARENTHESIZED_EXPRESSION && myContext.getSettings().ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION) + || (parentType == PyElementTypes.ARGUMENT_LIST && myContext.getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS) + || (parentType == PyElementTypes.PARAMETER_LIST && myContext.getSettings().ALIGN_MULTILINE_PARAMETERS)) && + !isIndentNext(child) && + !hasLineBreaksBefore(_node.getFirstChildNode(), 1) + && !ourListElementTypes.contains(childType)) { + + if (!ourBrackets.contains(childType)) { + childAlignment = getAlignmentForChildren(); + if (parentType != PyElementTypes.CALL_EXPRESSION) { + childIndent = Indent.getNormalIndent(); + } + } + else if (childType == PyTokenTypes.RPAR) { + childIndent = Indent.getNoneIndent(); + } + } + else if (parentType == PyElementTypes.GENERATOR_EXPRESSION || parentType == PyElementTypes.PARENTHESIZED_EXPRESSION) { if (childType == PyTokenTypes.RPAR || !hasLineBreaksBefore(child, 1)) { childIndent = Indent.getNoneIndent(); } @@ -244,6 +252,16 @@ public class PyBlock implements ASTBlock { childIndent = isIndentNext(child) ? Indent.getContinuationIndent() : Indent.getNormalIndent(); } } + else if (parentType == PyElementTypes.ARGUMENT_LIST || parentType == PyElementTypes.PARAMETER_LIST) { + if (childType == PyTokenTypes.RPAR) { + childIndent = Indent.getNoneIndent(); + } + else { + childIndent = parentType == PyElementTypes.PARAMETER_LIST || isInControlStatement() + ? Indent.getContinuationIndent() + : Indent.getNormalIndent(/*true*/); + } + } else if (parentType == PyElementTypes.SUBSCRIPTION_EXPRESSION) { PyExpression indexExpression = ((PySubscriptionExpression)_node.getPsi()).getIndexExpression(); if (indexExpression != null && child == indexExpression.getNode()) { @@ -254,9 +272,21 @@ public class PyBlock implements ASTBlock { if (child != _node.getFirstChildNode()) { childIndent = Indent.getNormalIndent(); if (hasLineBreaksBefore(child, 1)) { - if (isIndentNext(child)) { + if (isInControlStatement()) { childIndent = Indent.getContinuationIndent(); } + else { + PyBlock b = myParent; + while (b != null) { + if (b.getNode().getPsi() instanceof PyParenthesizedExpression || + b.getNode().getPsi() instanceof PyArgumentList || + b.getNode().getPsi() instanceof PyParameterList) { + childAlignment = getAlignmentOfChild(b, 1); + break; + } + b = b.myParent; + } + } } } } @@ -279,6 +309,14 @@ public class PyBlock implements ASTBlock { return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext); } + private static Alignment getAlignmentOfChild(PyBlock b, int childNum) { + if (b.getSubBlocks().size() > childNum) { + ChildAttributes attributes = b.getChildAttributes(childNum); + return attributes.getAlignment(); + } + return null; + } + private static boolean isIndentNext(ASTNode child) { PsiElement psi = PsiTreeUtil.getParentOfType(child.getPsi(), PyStatement.class); diff --git a/python/testData/formatter/alignInCallExpression.py b/python/testData/formatter/alignInCallExpression.py new file mode 100644 index 000000000000..0c1dff1290d9 --- /dev/null +++ b/python/testData/formatter/alignInCallExpression.py @@ -0,0 +1,3 @@ +foo(1 + + x. + call()) \ No newline at end of file diff --git a/python/testData/formatter/alignInCallExpression_after.py b/python/testData/formatter/alignInCallExpression_after.py new file mode 100644 index 000000000000..48c17a191559 --- /dev/null +++ b/python/testData/formatter/alignInCallExpression_after.py @@ -0,0 +1,3 @@ +foo(1 + + x. + call()) \ No newline at end of file diff --git a/python/testData/formatter/alignInParameterList.py b/python/testData/formatter/alignInParameterList.py new file mode 100644 index 000000000000..1a7976646dde --- /dev/null +++ b/python/testData/formatter/alignInParameterList.py @@ -0,0 +1,4 @@ +def foo(x= + y. + call()): + pass \ No newline at end of file diff --git a/python/testData/formatter/alignInParameterList_after.py b/python/testData/formatter/alignInParameterList_after.py new file mode 100644 index 000000000000..c3291b2612cb --- /dev/null +++ b/python/testData/formatter/alignInParameterList_after.py @@ -0,0 +1,4 @@ +def foo(x= + y. + call()): + pass \ No newline at end of file diff --git a/python/testData/formatter/alignInParenthesizedExpression.py b/python/testData/formatter/alignInParenthesizedExpression.py new file mode 100644 index 000000000000..ea97ade4ee92 --- /dev/null +++ b/python/testData/formatter/alignInParenthesizedExpression.py @@ -0,0 +1,8 @@ +print(1 + (1 + (1 + + + x + .calc()) + + + x. + calc() +)) \ No newline at end of file diff --git a/python/testData/formatter/alignInParenthesizedExpression_after.py b/python/testData/formatter/alignInParenthesizedExpression_after.py new file mode 100644 index 000000000000..868557ca748f --- /dev/null +++ b/python/testData/formatter/alignInParenthesizedExpression_after.py @@ -0,0 +1,8 @@ +print(1 + (1 + (1 + + + x + .calc()) + + + x. + calc() +)) \ No newline at end of file diff --git a/python/testData/formatter/wrapOnDot_after.py b/python/testData/formatter/wrapOnDot_after.py index c4f7e7edfeef..e42d177c67d8 100644 --- a/python/testData/formatter/wrapOnDot_after.py +++ b/python/testData/formatter/wrapOnDot_after.py @@ -1,2 +1,2 @@ sitesettings = call(settings_manager - .get_whitelabel_settings_by_site_id(myuser.site_id)) \ No newline at end of file + .get_whitelabel_settings_by_site_id(myuser.site_id)) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java index df03bec0ff8d..07af7e8f7ee3 100644 --- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java +++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java @@ -299,6 +299,10 @@ public class PyFormatterTest extends PyTestCase { doTest(); } + public void testAlignInCallExpression() { + doTest(); + } + public void testContinuationIndentForCallInStatementPart() { // PY-8577 doTest(); } @@ -307,7 +311,7 @@ public class PyFormatterTest extends PyTestCase { doTest(); } - public void _testIndentInNestedCall() { // PY-8195 + public void _testIndentInNestedCall() { // PY-11906 TODO: fix indent doTest(); } @@ -377,6 +381,14 @@ public class PyFormatterTest extends PyTestCase { public void testIndentParensInImport() { // PY-9075 doTest(); } + + public void testAlignInParenthesizedExpression() { + doTest(); + } + + public void testAlignInParameterList() { + doTest(); + } private void doTest() { doTest(false);