From 05b24439888bccc9888d7a4e96b8f4709f919dc4 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 27 Nov 2018 15:23:33 +0300 Subject: [PATCH] Make assignment indent conforms with indent for expression bodies (KT-28484) Do not make plain list of binary expression for assignment expressions. #KT-28484 Fixed --- .../idea/formatter/KotlinCommonBlock.kt | 30 +++++++++++++--- .../idea/formatter/NodeIndentStrategy.kt | 12 +++++++ ...ryExpressionsWithoutAlignment.after.inv.kt | 3 +- ...BinaryExpressionsWithoutAlignment.after.kt | 13 +++---- .../BinaryExpressionsWithoutAlignment.kt | 3 +- ...ontinuationIndentInAssigments.after.inv.kt | 36 +++++++++++++++++++ .../ContinuationIndentInAssigments.after.kt | 36 +++++++++++++++++++ .../ContinuationIndentInAssigments.kt | 36 +++++++++++++++++++ .../formatter/FormatterTestGenerated.java | 10 ++++++ 9 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 idea/testData/formatter/ContinuationIndentInAssigments.after.inv.kt create mode 100644 idea/testData/formatter/ContinuationIndentInAssigments.after.kt create mode 100644 idea/testData/formatter/ContinuationIndentInAssigments.kt diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt index ce29ebf2a6d..a493d7d2ac0 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -434,9 +434,14 @@ abstract class KotlinCommonBlock( val childNodes = when { overrideChildren != null -> overrideChildren.asSequence() node.elementType == KtNodeTypes.BINARY_EXPRESSION -> { - val binaryExpressionChildren = mutableListOf() - collectBinaryExpressionChildren(node, binaryExpressionChildren) - binaryExpressionChildren.asSequence() + val binaryExpression = node.psi as? KtBinaryExpression + if (binaryExpression != null && ALL_ASSIGNMENTS.contains(binaryExpression.operationToken)) { + node.children() + } else { + val binaryExpressionChildren = mutableListOf() + collectBinaryExpressionChildren(node, binaryExpressionChildren) + binaryExpressionChildren.asSequence() + } } else -> node.children() } @@ -725,6 +730,21 @@ private val INDENT_RULES = arrayOf( } .continuationIf(KotlinCodeStyleSettings::CONTINUATION_INDENT_FOR_EXPRESSION_BODIES), + strategy("Assignment expressions") + .within(KtNodeTypes.BINARY_EXPRESSION) + .within { + val binaryExpression = it.psi as? KtBinaryExpression + ?: return@within false + + return@within KtTokens.ALL_ASSIGNMENTS.contains(binaryExpression.operationToken) + } + .forElement { + val psi = it.psi + val binaryExpression = psi?.parent as? KtBinaryExpression + binaryExpression?.right == psi + } + .continuationIf(KotlinCodeStyleSettings::CONTINUATION_INDENT_FOR_EXPRESSION_BODIES), + strategy("Indent for parts") .within(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR) .notForType( @@ -755,7 +775,9 @@ private val INDENT_RULES = arrayOf( strategy("Binary expressions") .within(BINARY_EXPRESSIONS) - .forElement { node -> !node.suppressBinaryExpressionIndent() } + .forElement { node -> + !node.suppressBinaryExpressionIndent() + } .set(Indent.getContinuationWithoutFirstIndent(false)), strategy("Parenthesized expression") diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt index cd8ac958ec6..179ca318463 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt @@ -38,7 +38,10 @@ abstract class NodeIndentStrategy { private var indentCallback: (CodeStyleSettings) -> Indent = { Indent.getNoneIndent() } private val within = ArrayList() + private var withinCallback: ((ASTNode) -> Boolean)? = null + private val notIn = ArrayList() + private val forElement = ArrayList() private val notForElement = ArrayList() private var forElementCallback: ((ASTNode) -> Boolean)? = null @@ -72,6 +75,11 @@ abstract class NodeIndentStrategy { return this } + fun within(callback: (ASTNode) -> Boolean): PositionStrategy { + withinCallback = callback + return this + } + fun notWithin(parentType: IElementType, vararg orParentTypes: IElementType): PositionStrategy { fillTypes(notIn, parentType, orParentTypes) return this @@ -129,6 +137,10 @@ abstract class NodeIndentStrategy { if (notIn.contains(parent.elementType)) { return null } + + if (withinCallback?.invoke(parent) == false) { + return null + } } else { if (!within.isEmpty()) { diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt index 7a9dc9ae519..8fa1c5bd555 100644 --- a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.inv.kt @@ -35,4 +35,5 @@ fun test() { 1..2 } -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt index 7a9dc9ae519..6d6a1b14c37 100644 --- a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.after.kt @@ -2,19 +2,19 @@ fun test() { var a = 12 a = - 12 + 12 a += - 12 + 12 a -= - 12 + 12 a *= - 12 + 12 a /= - 12 + 12 a is String @@ -35,4 +35,5 @@ fun test() { 1..2 } -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt index 78c9a949725..9af4a1d0d61 100644 --- a/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt +++ b/idea/testData/formatter/BinaryExpressionsWithoutAlignment.kt @@ -35,4 +35,5 @@ fun test() { 1..2 } -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/testData/formatter/ContinuationIndentInAssigments.after.inv.kt b/idea/testData/formatter/ContinuationIndentInAssigments.after.inv.kt new file mode 100644 index 00000000000..acafe464a9a --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInAssigments.after.inv.kt @@ -0,0 +1,36 @@ +var a: Any? = null +var b: Any? = null + +var i = 0 +var j = 0 + +fun test() { + a1 = + 1 + + a = + b + + a = + "Some" + + i += + j * j + + i = + j ?: 0 + + i -= + j + + i *= + 0 + + i %= + 5 + + i /= + 2 +} + +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/testData/formatter/ContinuationIndentInAssigments.after.kt b/idea/testData/formatter/ContinuationIndentInAssigments.after.kt new file mode 100644 index 00000000000..e6c63336b33 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInAssigments.after.kt @@ -0,0 +1,36 @@ +var a: Any? = null +var b: Any? = null + +var i = 0 +var j = 0 + +fun test() { + a1 = + 1 + + a = + b + + a = + "Some" + + i += + j * j + + i = + j ?: 0 + + i -= + j + + i *= + 0 + + i %= + 5 + + i /= + 2 +} + +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/testData/formatter/ContinuationIndentInAssigments.kt b/idea/testData/formatter/ContinuationIndentInAssigments.kt new file mode 100644 index 00000000000..d5d2e334851 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInAssigments.kt @@ -0,0 +1,36 @@ +var a: Any? = null +var b: Any? = null + +var i = 0 +var j = 0 + +fun test() { + a1 = + 1 + + a = + b + + a = + "Some" + + i += + j * j + + i = + j ?: 0 + + i -= + j + + i *= + 0 + + i %= + 5 + + i /= + 2 +} + +// SET_FALSE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 57fc6c3407b..4510f87a81b 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -171,6 +171,11 @@ public class FormatterTestGenerated extends AbstractFormatterTest { runTest("idea/testData/formatter/CommentInFunctionLiteral.after.kt"); } + @TestMetadata("ContinuationIndentInAssigments.after.kt") + public void testContinuationIndentInAssigments() throws Exception { + runTest("idea/testData/formatter/ContinuationIndentInAssigments.after.kt"); + } + @TestMetadata("ContinuationIndentInParameterLists.after.kt") public void testContinuationIndentInParameterLists() throws Exception { runTest("idea/testData/formatter/ContinuationIndentInParameterLists.after.kt"); @@ -1136,6 +1141,11 @@ public class FormatterTestGenerated extends AbstractFormatterTest { runTest("idea/testData/formatter/ContinuationIndentForExpressionBodies.after.inv.kt"); } + @TestMetadata("ContinuationIndentInAssigments.after.inv.kt") + public void testContinuationIndentInAssigments() throws Exception { + runTest("idea/testData/formatter/ContinuationIndentInAssigments.after.inv.kt"); + } + @TestMetadata("DelegationList.after.inv.kt") public void testDelegationList() throws Exception { runTest("idea/testData/formatter/DelegationList.after.inv.kt");