From d4ddf06ebde4cf86dd12fcb2b9775ea0bc810fe9 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 14 May 2014 18:51:04 +0400 Subject: [PATCH] Fix problem with alignment in assignments and other binary expressions --- .../jet/plugin/formatter/JetBlock.java | 14 ++++++- .../plugin/formatter/NodeIndentStrategy.java | 12 ++++++ ...ryExpressionsWithoutAlignment.after.inv.kt | 41 +++++++++++++++++++ ...BinaryExpressionsWithoutAlignment.after.kt | 41 +++++++++++++++++++ .../BinaryExpressionsWithoutAlignment.kt | 41 +++++++++++++++++++ idea/testData/formatter/Elvis.after.inv.kt | 17 ++++++++ idea/testData/formatter/Elvis.after.kt | 12 ++++-- idea/testData/formatter/Elvis.kt | 8 +++- .../AssignmentAfterEq.after.inv.kt | 7 ++++ .../AssignmentAfterEq.after.kt | 7 ++++ .../indentationOnNewline/AssignmentAfterEq.kt | 6 +++ .../BinaryWithTypeExpressions.after.inv.kt | 7 ++++ .../BinaryWithTypeExpressions.after.kt | 7 ++++ .../BinaryWithTypeExpressions.kt | 6 +++ .../IsExpressionAfterIs.after.inv.kt | 6 +++ .../IsExpressionAfterIs.after.kt | 6 +++ .../IsExpressionAfterIs.kt | 5 +++ .../formatter/JetFormatterTestGenerated.java | 15 +++++++ ...JetTypingIndentationTestBaseGenerated.java | 34 ++++++++++++++- 19 files changed, 285 insertions(+), 7 deletions(-) create mode 100644 idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt create mode 100644 idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt create mode 100644 idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt create mode 100644 idea/testData/formatter/Elvis.after.inv.kt create mode 100644 idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt create mode 100644 idea/testData/indentationOnNewline/AssignmentAfterEq.after.kt create mode 100644 idea/testData/indentationOnNewline/AssignmentAfterEq.kt create mode 100644 idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.inv.kt create mode 100644 idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.kt create mode 100644 idea/testData/indentationOnNewline/BinaryWithTypeExpressions.kt create mode 100644 idea/testData/indentationOnNewline/IsExpressionAfterIs.after.inv.kt create mode 100644 idea/testData/indentationOnNewline/IsExpressionAfterIs.after.kt create mode 100644 idea/testData/indentationOnNewline/IsExpressionAfterIs.kt diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java index ac0be63a29e..77ce41d0b0e 100644 --- a/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java +++ b/idea/src/org/jetbrains/jet/plugin/formatter/JetBlock.java @@ -53,7 +53,11 @@ public class JetBlock extends AbstractBlock { private List mySubBlocks; + private static final TokenSet BINARY_EXPRESSIONS = TokenSet.create(BINARY_EXPRESSION, BINARY_WITH_TYPE, IS_EXPRESSION); private static final TokenSet QUALIFIED_OPERATION = TokenSet.create(DOT, SAFE_ACCESS); + private static final TokenSet ALIGN_FOR_BINARY_OPERATIONS = + TokenSet.create(MUL, DIV, PERC, PLUS, MINUS, ELVIS, LT, GT, LTEQ, GTEQ, ANDAND, OROR); + private static final TokenSet CODE_BLOCKS = TokenSet.create( BLOCK, CLASS_BODY, @@ -229,7 +233,7 @@ public class JetBlock extends AbstractBlock { else if (parentType == WHEN) { return getAlignmentForCaseBranch(jetSettings.ALIGN_IN_COLUMNS_CASE_BRANCH); } - else if (parentType == BINARY_EXPRESSION) { + else if (BINARY_EXPRESSIONS.contains(parentType) && ALIGN_FOR_BINARY_OPERATIONS.contains(getOperationType(getNode()))) { return NodeAlignmentStrategy.fromTypes(AlignmentStrategy.wrap( createAlignment(jetCommonSettings.ALIGN_MULTILINE_BINARY_OPERATION, getAlignment()))); } @@ -352,7 +356,7 @@ public class JetBlock extends AbstractBlock { .set(Indent.getContinuationIndent(false)), strategy("Binary expressions") - .in(BINARY_EXPRESSION) + .in(BINARY_EXPRESSIONS) .set(Indent.getContinuationWithoutFirstIndent(false)), strategy("Parenthesized expression") @@ -434,4 +438,10 @@ public class JetBlock extends AbstractBlock { } }); } + + @Nullable + private static IElementType getOperationType(ASTNode node) { + ASTNode operationNode = node.findChildByType(OPERATION_REFERENCE); + return operationNode != null ? operationNode.getFirstChildNode().getElementType() : null; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/NodeIndentStrategy.java b/idea/src/org/jetbrains/jet/plugin/formatter/NodeIndentStrategy.java index 8b3b12bfe20..c0aa44d6e8f 100644 --- a/idea/src/org/jetbrains/jet/plugin/formatter/NodeIndentStrategy.java +++ b/idea/src/org/jetbrains/jet/plugin/formatter/NodeIndentStrategy.java @@ -19,10 +19,12 @@ package org.jetbrains.jet.plugin.formatter; import com.intellij.formatting.Indent; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -77,6 +79,16 @@ public abstract class NodeIndentStrategy { return this; } + public PositionStrategy in(@NotNull TokenSet parents) { + IElementType[] types = parents.getTypes(); + if (types.length == 0) { + throw new IllegalArgumentException("Empty token set is unexpected"); + } + + fillTypes(in, types[0], Arrays.copyOfRange(types, 1, types.length)); + return this; + } + public PositionStrategy in(@NotNull IElementType parentType, @NotNull IElementType... orParentTypes) { fillTypes(in, parentType, orParentTypes); return this; diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt new file mode 100644 index 00000000000..8e1d3a5398c --- /dev/null +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt @@ -0,0 +1,41 @@ +fun test() { + var a = 12 + + a = + 12 + + a += + 12 + + a -= + 12 + + a *= + 12 + + a /= + 12 + + a is + String + + a !is + String + + a as + String + + a as? + String + + a : + String + + a in + 1..2 + + a !in + 1..2 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt new file mode 100644 index 00000000000..8e1d3a5398c --- /dev/null +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt @@ -0,0 +1,41 @@ +fun test() { + var a = 12 + + a = + 12 + + a += + 12 + + a -= + 12 + + a *= + 12 + + a /= + 12 + + a is + String + + a !is + String + + a as + String + + a as? + String + + a : + String + + a in + 1..2 + + a !in + 1..2 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt new file mode 100644 index 00000000000..ddd894bdafc --- /dev/null +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt @@ -0,0 +1,41 @@ +fun test() { + var a = 12 + + a = + 12 + + a += + 12 + + a -= + 12 + + a *= + 12 + + a /= + 12 + + a is + String + + a !is + String + + a as + String + + a as? + String + + a : + String + + a in + 1..2 + + a !in + 1..2 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/formatter/Elvis.after.inv.kt b/idea/testData/formatter/Elvis.after.inv.kt new file mode 100644 index 00000000000..07669066a0c --- /dev/null +++ b/idea/testData/formatter/Elvis.after.inv.kt @@ -0,0 +1,17 @@ +fun test(a: Int?) { + a ?: 42 + + a ?: 42 + + a ?: + 42 + + a + ?: 42 + + val some = a ?: + b ?: + 12 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/formatter/Elvis.after.kt b/idea/testData/formatter/Elvis.after.kt index b3ab559fb91..0cdda628877 100644 --- a/idea/testData/formatter/Elvis.after.kt +++ b/idea/testData/formatter/Elvis.after.kt @@ -4,8 +4,14 @@ fun test(a: Int?) { a ?: 42 a ?: - 42 + 42 a - ?: 42 -} \ No newline at end of file + ?: 42 + + val some = a ?: + b ?: + 12 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/formatter/Elvis.kt b/idea/testData/formatter/Elvis.kt index c294cb65de4..c45a121621f 100644 --- a/idea/testData/formatter/Elvis.kt +++ b/idea/testData/formatter/Elvis.kt @@ -8,4 +8,10 @@ fun test(a: Int?) { a ?: 42 -} \ No newline at end of file + + val some = a ?: + b ?: + 12 +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt b/idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt new file mode 100644 index 00000000000..a1f26e1903f --- /dev/null +++ b/idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt @@ -0,0 +1,7 @@ +fun test() { + var a = 1 + a = + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/AssignmentAfterEq.after.kt b/idea/testData/indentationOnNewline/AssignmentAfterEq.after.kt new file mode 100644 index 00000000000..a1f26e1903f --- /dev/null +++ b/idea/testData/indentationOnNewline/AssignmentAfterEq.after.kt @@ -0,0 +1,7 @@ +fun test() { + var a = 1 + a = + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/AssignmentAfterEq.kt b/idea/testData/indentationOnNewline/AssignmentAfterEq.kt new file mode 100644 index 00000000000..3fab3cebaef --- /dev/null +++ b/idea/testData/indentationOnNewline/AssignmentAfterEq.kt @@ -0,0 +1,6 @@ +fun test() { + var a = 1 + a = +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.inv.kt b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.inv.kt new file mode 100644 index 00000000000..689f0b38de0 --- /dev/null +++ b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.inv.kt @@ -0,0 +1,7 @@ +fun test() { + var a = 1 + a as + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.kt b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.kt new file mode 100644 index 00000000000..689f0b38de0 --- /dev/null +++ b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.kt @@ -0,0 +1,7 @@ +fun test() { + var a = 1 + a as + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.kt b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.kt new file mode 100644 index 00000000000..905dc43362e --- /dev/null +++ b/idea/testData/indentationOnNewline/BinaryWithTypeExpressions.kt @@ -0,0 +1,6 @@ +fun test() { + var a = 1 + a as +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.inv.kt b/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.inv.kt new file mode 100644 index 00000000000..11889cf023e --- /dev/null +++ b/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.inv.kt @@ -0,0 +1,6 @@ +fun test() { + 1 is + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.kt b/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.kt new file mode 100644 index 00000000000..11889cf023e --- /dev/null +++ b/idea/testData/indentationOnNewline/IsExpressionAfterIs.after.kt @@ -0,0 +1,6 @@ +fun test() { + 1 is + +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/IsExpressionAfterIs.kt b/idea/testData/indentationOnNewline/IsExpressionAfterIs.kt new file mode 100644 index 00000000000..3db4a1ee59b --- /dev/null +++ b/idea/testData/indentationOnNewline/IsExpressionAfterIs.kt @@ -0,0 +1,5 @@ +fun test() { + 1 is +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/formatter/JetFormatterTestGenerated.java b/idea/tests/org/jetbrains/jet/formatter/JetFormatterTestGenerated.java index a36e353cf4a..f4acb883213 100644 --- a/idea/tests/org/jetbrains/jet/formatter/JetFormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/formatter/JetFormatterTestGenerated.java @@ -54,6 +54,11 @@ public class JetFormatterTestGenerated extends AbstractJetFormatterTest { doTest("idea/testData/formatter/BinaryExpressionsBoolean.after.kt"); } + @TestMetadata("BinaryExpressionsWithoutAlignment.after.kt") + public void testBinaryExpressionsWithoutAlignment() throws Exception { + doTest("idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt"); + } + @TestMetadata("BlockFor.after.kt") public void testBlockFor() throws Exception { doTest("idea/testData/formatter/BlockFor.after.kt"); @@ -479,6 +484,11 @@ public class JetFormatterTestGenerated extends AbstractJetFormatterTest { doTestInverted("idea/testData/formatter/BinaryExpressionsBoolean.after.inv.kt"); } + @TestMetadata("BinaryExpressionsWithoutAlignment.after.inv.kt") + public void testBinaryExpressionsWithoutAlignment() throws Exception { + doTestInverted("idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt"); + } + @TestMetadata("CatchFinallyOnNewLine.after.inv.kt") public void testCatchFinallyOnNewLine() throws Exception { doTestInverted("idea/testData/formatter/CatchFinallyOnNewLine.after.inv.kt"); @@ -509,6 +519,11 @@ public class JetFormatterTestGenerated extends AbstractJetFormatterTest { doTestInverted("idea/testData/formatter/ElseOnNewLine.after.inv.kt"); } + @TestMetadata("Elvis.after.inv.kt") + public void testElvis() throws Exception { + doTestInverted("idea/testData/formatter/Elvis.after.inv.kt"); + } + @TestMetadata("EmptyBlocks.after.inv.kt") public void testEmptyBlocks() throws Exception { doTestInverted("idea/testData/formatter/EmptyBlocks.after.inv.kt"); diff --git a/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java index 26193d1d8b8..facab36b478 100644 --- a/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java +++ b/idea/tests/org/jetbrains/jet/formatter/JetTypingIndentationTestBaseGenerated.java @@ -61,7 +61,19 @@ public class JetTypingIndentationTestBaseGenerated extends AbstractJetTypingInde } public void testAllFilesPresentInDirectSettings() throws Exception { - JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/indentationOnNewline"), Pattern.compile("^([^\\.]+)\\.after\\.kt.*$"), true); + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", + new File("idea/testData/indentationOnNewline"), + Pattern.compile("^([^\\.]+)\\.after\\.kt.*$"), true); + } + + @TestMetadata("AssignmentAfterEq.after.kt") + public void testAssignmentAfterEq() throws Exception { + doNewlineTest("idea/testData/indentationOnNewline/AssignmentAfterEq.after.kt"); + } + + @TestMetadata("BinaryWithTypeExpressions.after.kt") + public void testBinaryWithTypeExpressions() throws Exception { + doNewlineTest("idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.kt"); } @TestMetadata("ConsecutiveCallsAfterDot.after.kt") @@ -204,6 +216,11 @@ public class JetTypingIndentationTestBaseGenerated extends AbstractJetTypingInde doNewlineTest("idea/testData/indentationOnNewline/InMultilineLambdaAfterArrow.after.kt"); } + @TestMetadata("IsExpressionAfterIs.after.kt") + public void testIsExpressionAfterIs() throws Exception { + doNewlineTest("idea/testData/indentationOnNewline/IsExpressionAfterIs.after.kt"); + } + @TestMetadata("MultideclarationAfterEq.after.kt") public void testMultideclarationAfterEq() throws Exception { doNewlineTest("idea/testData/indentationOnNewline/MultideclarationAfterEq.after.kt"); @@ -282,6 +299,16 @@ public class JetTypingIndentationTestBaseGenerated extends AbstractJetTypingInde JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/indentationOnNewline"), Pattern.compile("^([^\\.]+)\\.after\\.inv\\.kt.*$"), true); } + @TestMetadata("AssignmentAfterEq.after.inv.kt") + public void testAssignmentAfterEq() throws Exception { + doNewlineTestWithInvert("idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt"); + } + + @TestMetadata("BinaryWithTypeExpressions.after.inv.kt") + public void testBinaryWithTypeExpressions() throws Exception { + doNewlineTestWithInvert("idea/testData/indentationOnNewline/BinaryWithTypeExpressions.after.inv.kt"); + } + @TestMetadata("InBinaryExpressionInMiddle.after.inv.kt") public void testInBinaryExpressionInMiddle() throws Exception { doNewlineTestWithInvert("idea/testData/indentationOnNewline/InBinaryExpressionInMiddle.after.inv.kt"); @@ -337,6 +364,11 @@ public class JetTypingIndentationTestBaseGenerated extends AbstractJetTypingInde doNewlineTestWithInvert("idea/testData/indentationOnNewline/InExpressionsParenthesesBeforeOperand.after.inv.kt"); } + @TestMetadata("IsExpressionAfterIs.after.inv.kt") + public void testIsExpressionAfterIs() throws Exception { + doNewlineTestWithInvert("idea/testData/indentationOnNewline/IsExpressionAfterIs.after.inv.kt"); + } + @TestMetadata("SettingAlignMultilineParametersInCalls.after.inv.kt") public void testSettingAlignMultilineParametersInCalls() throws Exception { doNewlineTestWithInvert("idea/testData/indentationOnNewline/SettingAlignMultilineParametersInCalls.after.inv.kt");