From e021c62e114dcf4216562aaaac0ba8461fc257c2 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Thu, 9 Jun 2022 12:50:40 +0200 Subject: [PATCH] [kotlin][indent] line indent provider: support indent before close parenthesis ^KTIJ-21962 Fixed ^FL-11758 GitOrigin-RevId: 60db3034642ef58dcb0f0824d54068ab5299c981 --- .../formatter/KotlinLineIndentProvider.kt | 17 +++- .../formatter/EnterHandlerTestGenerated.java | 30 ++++--- .../KotlinSuggestedRefactoringTest.kt | 4 +- .../editor/enterHandler/LargeFile.after.kt | 6 +- .../testData/editor/enterHandler/LargeFile.kt | 4 +- .../NotFirstParameter.after.inv.kt | 2 +- .../enterHandler/NotFirstParameter.after.kt | 4 +- .../editor/enterHandler/NotFirstParameter.kt | 2 +- ...ignMultilineParametersInCalls.after.inv.kt | 4 +- ...ngAlignMultilineParametersInCalls.after.kt | 4 +- .../SettingAlignMultilineParametersInCalls.kt | 2 +- ...singBracketInMethodParameters.after.inv.kt | 2 +- ...eClosingBracketInMethodParameters.after.kt | 4 +- ...kBeforeClosingBracketInMethodParameters.kt | 2 +- ...inaryExpressionUnfinishedInIf.after.inv.kt | 7 -- .../InBinaryExpressionUnfinishedInIf.after.kt | 3 +- .../InBinaryExpressionUnfinishedInIf.kt | 3 +- ...BinaryExpressionUnfinishedInIfInv.after.kt | 7 ++ .../InBinaryExpressionUnfinishedInIfInv.kt | 6 ++ ...essionsBeforeCloseParenthesis.after.inv.kt | 5 -- ...ExpressionsBeforeCloseParenthesis.after.kt | 4 +- ...BinaryExpressionsBeforeCloseParenthesis.kt | 2 +- ...ressionsBeforeCloseParenthesisInv.after.kt | 4 + ...aryExpressionsBeforeCloseParenthesisInv.kt | 3 + .../lineIndent/KotlinIndentationAdjuster.kt | 22 ++++- .../KotlinLangLineIndentProvider.kt | 81 ++++++++++++++----- ...ormanceTypingIndentationTestGenerated.java | 30 ++++--- 27 files changed, 185 insertions(+), 79 deletions(-) delete mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt create mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt create mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.kt delete mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt create mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt create mode 100644 plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.kt diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt index fff19fa5b222..9b9a7ef075bc 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.formatter @@ -31,6 +31,21 @@ class KotlinLineIndentProvider : KotlinLangLineIndentProvider() { override val continuationIndentForExpressionBodies: Boolean get() = settings.kotlinCustomSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES + + override val alignMultilineParameters: Boolean + get() = settings.kotlinCommonSettings.ALIGN_MULTILINE_PARAMETERS + + override val alignMultilineParametersInCalls: Boolean + get() = settings.kotlinCommonSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS + + override val continuationIndentInArgumentLists: Boolean + get() = settings.kotlinCustomSettings.CONTINUATION_INDENT_IN_ARGUMENT_LISTS + + override val continuationIndentInParameterLists: Boolean + get() = settings.kotlinCustomSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS + + override val continuationIndentInIfCondition: Boolean + get() = settings.kotlinCustomSettings.CONTINUATION_INDENT_IN_IF_CONDITIONS } companion object { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/formatter/EnterHandlerTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/formatter/EnterHandlerTestGenerated.java index a46d9b7d494d..ec0f2cecc9a4 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/formatter/EnterHandlerTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/formatter/EnterHandlerTestGenerated.java @@ -844,11 +844,21 @@ public abstract class EnterHandlerTestGenerated extends AbstractEnterHandlerTest runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt"); } + @TestMetadata("InBinaryExpressionUnfinishedInIfInv.after.kt") + public void testInBinaryExpressionUnfinishedInIfInv() throws Exception { + runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt"); + } + @TestMetadata("InBinaryExpressionsBeforeCloseParenthesis.after.kt") public void testInBinaryExpressionsBeforeCloseParenthesis() throws Exception { runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt"); } + @TestMetadata("InBinaryExpressionsBeforeCloseParenthesisInv.after.kt") + public void testInBinaryExpressionsBeforeCloseParenthesisInv() throws Exception { + runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt"); + } + @TestMetadata("InExpressionsParentheses.after.kt") public void testInExpressionsParentheses() throws Exception { runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InExpressionsParentheses.after.kt"); @@ -1971,16 +1981,6 @@ public abstract class EnterHandlerTestGenerated extends AbstractEnterHandlerTest runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinished.after.inv.kt"); } - @TestMetadata("InBinaryExpressionUnfinishedInIf.after.inv.kt") - public void testInBinaryExpressionUnfinishedInIf() throws Exception { - runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt"); - } - - @TestMetadata("InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt") - public void testInBinaryExpressionsBeforeCloseParenthesis() throws Exception { - runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt"); - } - @TestMetadata("InExpressionsParenthesesBeforeOperand.after.inv.kt") public void testInExpressionsParenthesesBeforeOperand() throws Exception { runTest("testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InExpressionsParenthesesBeforeOperand.after.inv.kt"); @@ -2137,10 +2137,20 @@ public abstract class EnterHandlerTestGenerated extends AbstractEnterHandlerTest runTest("testData/editor/enterHandler/InEnumInitializerListNotEmpty.after.inv.kt"); } + @TestMetadata("NotFirstParameter.after.inv.kt") + public void testNotFirstParameter() throws Exception { + runTest("testData/editor/enterHandler/NotFirstParameter.after.inv.kt"); + } + @TestMetadata("SettingAlignMultilineParametersInCalls.after.inv.kt") public void testSettingAlignMultilineParametersInCalls() throws Exception { runTest("testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt"); } + + @TestMetadata("SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt") + public void testSmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters() throws Exception { + runTest("testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt"); + } } } } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/suggested/KotlinSuggestedRefactoringTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/suggested/KotlinSuggestedRefactoringTest.kt index ace88056bb3a..e73027ba5e2b 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/suggested/KotlinSuggestedRefactoringTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/suggested/KotlinSuggestedRefactoringTest.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.refactoring.suggested @@ -491,7 +491,7 @@ class KotlinSuggestedRefactoringTest : BaseSuggestedRefactoringTest() { interface I { fun foo(p1: Int/*comment 1*/, p2: Long/*comment 2*/, - p3: Any?/*comment 3*/) + p3: Any?/*comment 3*/) } """.trimIndent(), "usages", diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.after.kt index 133b03a4aadd..36bb8d1d56b0 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.after.kt @@ -312,7 +312,7 @@ private val TYPES_WITH_TRAILING_COMMA_ON_CALL_SITE = TokenSet.create( KtNodeTypes.TYPE_ARGUMENT_LIST, KtNodeTypes.INDICES, KtNodeTypes.VALUE_ARGUMENT_LIST, -) + ) fun UserDataHolder.addTrailingCommaIsAllowedForThis(): Boolean { val type = when (this) { @@ -2322,5 +2322,5 @@ private fun ASTNode.suppressBinaryExpressionIndent(): Boolean { return psi.parent?.node?.elementType == CONDITION || psi.operationToken == ELVIS } -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER -// SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS \ No newline at end of file +// SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.kt index 5b4aaaf28211..cd5744b7e9a6 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/LargeFile.kt @@ -2321,5 +2321,5 @@ private fun ASTNode.suppressBinaryExpressionIndent(): Boolean { return psi.parent?.node?.elementType == CONDITION || psi.operationToken == ELVIS } -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER -// SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS \ No newline at end of file +// SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.inv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.inv.kt index 7cdd55952de9..2a4b9b1b5274 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.inv.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.inv.kt @@ -3,4 +3,4 @@ fun testParam(a : String, b : Int, } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.kt index 27af0b2904ad..1af70e40469a 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.after.kt @@ -1,6 +1,6 @@ fun testParam(a : String, b : Int, -) { + ) { } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.kt index 70042f9c6367..8073c8a86d17 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/NotFirstParameter.kt @@ -2,4 +2,4 @@ fun testParam(a : String, b : Int,) { } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt index bdf1c212efc7..d97fcbcfaf62 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt @@ -1,7 +1,7 @@ fun test() { testVeryLong(12, - ) + ) } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.kt index 3c2b2b465638..2a5818247c78 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.kt @@ -1,7 +1,7 @@ fun test() { testVeryLong(12, - ) + ) } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.kt index a57c8f762ac4..eaa757cd5e8a 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.kt @@ -3,4 +3,4 @@ fun test() { } // SET_FALSE: ALIGN_MULTILINE_PARAMETERS_IN_CALLS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt index 8aecabb09fca..9a87dc963936 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt @@ -1,6 +1,6 @@ // SET_TRUE: SMART_TABS // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER +// IGNORE_FORMATTER fun method( arg1: String, diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.kt index a0cfa2c17195..2c3837e8943b 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.kt @@ -1,7 +1,7 @@ // SET_TRUE: SMART_TABS // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER +// IGNORE_FORMATTER fun method( arg1: String, -) {} + ) {} diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.kt index f26ac837a568..531cfd31b356 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.kt @@ -1,6 +1,6 @@ // SET_TRUE: SMART_TABS // SET_FALSE: ALIGN_MULTILINE_PARAMETERS -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER +// IGNORE_FORMATTER fun method( arg1: String,) {} diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt deleted file mode 100644 index 7cb777ede69b..000000000000 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt +++ /dev/null @@ -1,7 +0,0 @@ -fun test() { - if (true && - ) -} - -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt index 7cb777ede69b..44c1913ec7aa 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt @@ -3,5 +3,4 @@ fun test() { ) } -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// SET_TRUE: CONTINUATION_INDENT_IN_IF_CONDITIONS diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.kt index b7d5e0f1464d..05cd5cd18244 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.kt @@ -2,5 +2,4 @@ fun test() { if (true &&) } -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// SET_TRUE: CONTINUATION_INDENT_IN_IF_CONDITIONS diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt new file mode 100644 index 000000000000..bc3d7901520d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt @@ -0,0 +1,7 @@ +fun test() { + if (true && + ) +} + +// SET_FALSE: CONTINUATION_INDENT_IN_IF_CONDITIONS +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.kt new file mode 100644 index 000000000000..51de63d789d2 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.kt @@ -0,0 +1,6 @@ +fun test() { + if (true &&) +} + +// SET_FALSE: CONTINUATION_INDENT_IN_IF_CONDITIONS +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt deleted file mode 100644 index 81cf85304f4b..000000000000 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt +++ /dev/null @@ -1,5 +0,0 @@ -val somelong = 3 + 4 - (3 + - ) - -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt index b552b3a85fb5..68e86aad62bd 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt @@ -1,5 +1,5 @@ val somelong = 3 + 4 - (3 + - ) + ) // SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.kt index d5a3e96d0a8c..32a40dea8f3f 100644 --- a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.kt +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.kt @@ -1,4 +1,4 @@ val somelong = 3 + 4 - (3 + ) // SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file +// IGNORE_FORMATTER \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt new file mode 100644 index 000000000000..b0e68aa74eae --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt @@ -0,0 +1,4 @@ +val somelong = 3 + 4 - (3 + + ) + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.kt b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.kt new file mode 100644 index 000000000000..7198bb8cdd8c --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.kt @@ -0,0 +1,3 @@ +val somelong = 3 + 4 - (3 + ) + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION \ No newline at end of file diff --git a/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinIndentationAdjuster.kt b/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinIndentationAdjuster.kt index 5a8253d9b1cd..1efc140c247f 100644 --- a/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinIndentationAdjuster.kt +++ b/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinIndentationAdjuster.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.formatter.lineIndent @@ -18,4 +18,24 @@ interface KotlinIndentationAdjuster { // CONTINUATION_INDENT_FOR_EXPRESSION_BODIES val continuationIndentForExpressionBodies: Boolean get() = false + + // ALIGN_MULTILINE_PARAMETERS + val alignMultilineParameters: Boolean + get() = true + + // ALIGN_MULTILINE_PARAMETERS_IN_CALLS + val alignMultilineParametersInCalls: Boolean + get() = false + + // CONTINUATION_INDENT_IN_PARAMETER_LISTS + val continuationIndentInParameterLists: Boolean + get() = false + + // CONTINUATION_INDENT_IN_ARGUMENT_LISTS + val continuationIndentInArgumentLists: Boolean + get() = false + + // CONTINUATION_INDENT_IN_IF_CONDITIONS + val continuationIndentInIfCondition: Boolean + get() = false } \ No newline at end of file diff --git a/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLangLineIndentProvider.kt b/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLangLineIndentProvider.kt index 075a0b2256cb..0042e9bbd4a4 100644 --- a/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLangLineIndentProvider.kt +++ b/plugins/kotlin/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLangLineIndentProvider.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.formatter.lineIndent @@ -109,7 +109,7 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() { } } - before.isAt(LeftParenthesis) && after.isAt(RightParenthesis) -> + after.isAt(RightParenthesis) -> factory.createIndentCalculatorForParenthesis(before, currentPosition, after, offset, settings)?.let { return it } } @@ -225,7 +225,7 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() { return createIndentCalculator(defaultIndent, 0) } - if (after.after().afterOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET).isAt(Comma)) { + if (after.afterIgnoringWhiteSpaceOrComment().isAt(Comma)) { return createIndentCalculator(createAlignMultilineIndent(leftBrace), leftBrace.startOffset) } @@ -242,46 +242,80 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() { } private fun IndentCalculatorFactory.createIndentCalculatorForParenthesis( - leftParenthesis: SemanticEditorPosition, + before: SemanticEditorPosition, currentPosition: SemanticEditorPosition, rightParenthesis: SemanticEditorPosition, offset: Int, settings: KotlinIndentationAdjuster, ): IndentCalculator? { - assert(leftParenthesis.isAt(LeftParenthesis)) assert(rightParenthesis.isAt(RightParenthesis)) + val leftParenthesis = currentPosition.findLeftParenthesisBackwardsSkippingNested(LeftParenthesis, RightParenthesis) + if (!leftParenthesis.isAt(LeftParenthesis)) return null + // case only for caret before [RightParenthesis] if (!currentPosition.hasLineBreaksAfter(offset)) { - val indentForParentheses by lazy { - if (settings.alignWhenMultilineFunctionParentheses) createAlignMultilineIndent(leftParenthesis) else Indent.getNoneIndent() + fun createIndent( + isParameterList: Boolean, + baseLineOffset: Int, + ): IndentCalculator { + val indent = if (before.isAt(Comma)) { + when { + isParameterList && settings.alignMultilineParameters || + !isParameterList && settings.alignMultilineParametersInCalls -> { + val firstElement = leftParenthesis.afterIgnoringWhiteSpaceOrComment() + return createIndentCalculator(createAlignMultilineIndent(firstElement), firstElement.startOffset) + } + + isParameterList && settings.continuationIndentInParameterLists || + !isParameterList && settings.continuationIndentInArgumentLists -> Indent.getContinuationIndent() + + else -> Indent.getNormalIndent() + } + } else { + if (settings.alignWhenMultilineFunctionParentheses) + createAlignMultilineIndent(leftParenthesis) + else + Indent.getNoneIndent() + } + + return createIndentCalculator(indent, baseLineOffset) } findFunctionKeywordBeforeIdentifier(leftParenthesis.beforeIgnoringWhiteSpaceOrComment())?.let { - return createIndentCalculator(indentForParentheses, it.startOffset) + return createIndent(isParameterList = true, it.startOffset) } // NB: this covered [KtTokens.CONSTRUCTOR_KEYWORD], [KtTokens.SET_KEYWORD], [KtTokens.GET_KEYWORD], [KtTokens.INIT_KEYWORD] as well if (isSimilarToFunctionInvocation(leftParenthesis)) { - return createIndentCalculator(indentForParentheses, leftParenthesis.startOffset) + return createIndent(isParameterList = false, leftParenthesis.startOffset) } if (isDestructuringDeclaration(leftParenthesis, rightParenthesis)) { - return createIndentCalculator(Indent.getNoneIndent(), leftParenthesis.startOffset) + return createIndentCalculator( + if (before.isAt(Comma)) Indent.getNormalIndent() else Indent.getNoneIndent(), + leftParenthesis.startOffset + ) } leftParenthesis.beforeIgnoringWhiteSpaceOrComment().let { keyword -> - if (keyword.isControlFlowKeyword()) { - return createIndentCalculator(Indent.getNoneIndent(), keyword.startOffset) + val indent = when { + keyword.isAt(IfKeyword) && !before.isAt(LeftParenthesis) -> + if (settings.continuationIndentInIfCondition) Indent.getContinuationIndent() else Indent.getNormalIndent() + + keyword.isControlFlowKeyword() -> Indent.getNoneIndent() + else -> null } + + indent?.let { return createIndentCalculator(it, keyword.startOffset) } } - val indentForBinaryExpression = if (settings.alignWhenMultilineBinaryExpression) - createAlignMultilineIndent(leftParenthesis) - else - Indent.getContinuationIndent() - - return createIndentCalculator(indentForBinaryExpression, leftParenthesis.startOffset) + return if (settings.alignWhenMultilineBinaryExpression) { + val anchor = if (before.isAt(LeftParenthesis)) leftParenthesis else leftParenthesis.afterIgnoringWhiteSpaceOrComment() + createIndentCalculator(createAlignMultilineIndent(anchor), anchor.startOffset) + } else { + createIndentCalculator(Indent.getContinuationIndent(), leftParenthesis.startOffset) + } } return null @@ -510,10 +544,12 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() { if (--whileKeywordLevel == 0) return true moveBefore() } + isAt(WhileKeyword) -> { ++whileKeywordLevel moveBefore() } + isAt(BlockClosingBrace) -> moveBeforeParentheses(BlockOpeningBrace, BlockClosingBrace) else -> moveBefore() } @@ -573,12 +609,21 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() { private fun SemanticEditorPosition.moveBeforeWhileThisIsWhiteSpaceOrComment() = moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) + private fun SemanticEditorPosition.moveAfterWhileThisIsWhiteSpaceOrComment() = + moveAfterOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) + private fun SemanticEditorPosition.moveBeforeIgnoringWhiteSpaceOrComment() { moveBefore() moveBeforeWhileThisIsWhiteSpaceOrComment() } + private fun SemanticEditorPosition.moveAfterIgnoringWhiteSpaceOrComment() { + moveAfter() + moveAfterWhileThisIsWhiteSpaceOrComment() + } + private fun SemanticEditorPosition.beforeIgnoringWhiteSpaceOrComment() = copyAnd { it.moveBeforeIgnoringWhiteSpaceOrComment() } + private fun SemanticEditorPosition.afterIgnoringWhiteSpaceOrComment() = copyAnd { it.moveAfterIgnoringWhiteSpaceOrComment() } private fun SemanticEditorPosition.moveBeforeWhileThisIsWhiteSpaceOnSameLineOrBlockComment(): Boolean { while (!isAtEnd) { if (isAt(Whitespace) && isAtMultiline) return false diff --git a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceTypingIndentationTestGenerated.java b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceTypingIndentationTestGenerated.java index e7b1a7f9e566..769cb5d50c8b 100644 --- a/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceTypingIndentationTestGenerated.java +++ b/plugins/kotlin/performance-tests/test/org/jetbrains/kotlin/idea/perf/synthetic/PerformanceTypingIndentationTestGenerated.java @@ -844,11 +844,21 @@ public abstract class PerformanceTypingIndentationTestGenerated extends Abstract runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.kt"); } + @TestMetadata("InBinaryExpressionUnfinishedInIfInv.after.kt") + public void testInBinaryExpressionUnfinishedInIfInv() throws Exception { + runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIfInv.after.kt"); + } + @TestMetadata("InBinaryExpressionsBeforeCloseParenthesis.after.kt") public void testInBinaryExpressionsBeforeCloseParenthesis() throws Exception { runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.kt"); } + @TestMetadata("InBinaryExpressionsBeforeCloseParenthesisInv.after.kt") + public void testInBinaryExpressionsBeforeCloseParenthesisInv() throws Exception { + runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesisInv.after.kt"); + } + @TestMetadata("InExpressionsParentheses.after.kt") public void testInExpressionsParentheses() throws Exception { runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InExpressionsParentheses.after.kt"); @@ -1971,16 +1981,6 @@ public abstract class PerformanceTypingIndentationTestGenerated extends Abstract runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinished.after.inv.kt"); } - @TestMetadata("InBinaryExpressionUnfinishedInIf.after.inv.kt") - public void testInBinaryExpressionUnfinishedInIf() throws Exception { - runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionUnfinishedInIf.after.inv.kt"); - } - - @TestMetadata("InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt") - public void testInBinaryExpressionsBeforeCloseParenthesis() throws Exception { - runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InBinaryExpressionsBeforeCloseParenthesis.after.inv.kt"); - } - @TestMetadata("InExpressionsParenthesesBeforeOperand.after.inv.kt") public void testInExpressionsParenthesesBeforeOperand() throws Exception { runTest("../idea/tests/testData/editor/enterHandler/emptyParenthesisInBinaryExpression/InExpressionsParenthesesBeforeOperand.after.inv.kt"); @@ -2137,10 +2137,20 @@ public abstract class PerformanceTypingIndentationTestGenerated extends Abstract runTest("../idea/tests/testData/editor/enterHandler/InEnumInitializerListNotEmpty.after.inv.kt"); } + @TestMetadata("NotFirstParameter.after.inv.kt") + public void testNotFirstParameter() throws Exception { + runTest("../idea/tests/testData/editor/enterHandler/NotFirstParameter.after.inv.kt"); + } + @TestMetadata("SettingAlignMultilineParametersInCalls.after.inv.kt") public void testSettingAlignMultilineParametersInCalls() throws Exception { runTest("../idea/tests/testData/editor/enterHandler/SettingAlignMultilineParametersInCalls.after.inv.kt"); } + + @TestMetadata("SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt") + public void testSmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters() throws Exception { + runTest("../idea/tests/testData/editor/enterHandler/SmartEnterWithoutLineBreakBeforeClosingBracketInMethodParameters.after.inv.kt"); + } } } }