diff --git a/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/editor/EnterBetweenBracesAndBracketsNoCommitDelegate.kt b/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/editor/EnterBetweenBracesAndBracketsNoCommitDelegate.kt new file mode 100644 index 00000000000..580b3969a63 --- /dev/null +++ b/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/editor/EnterBetweenBracesAndBracketsNoCommitDelegate.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.editor + +import com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesNoCommitDelegate +import com.intellij.psi.tree.IElementType +import org.jetbrains.kotlin.lexer.KtTokens + +class EnterBetweenBracesAndBracketsNoCommitDelegate : EnterBetweenBracesNoCommitDelegate() { + override fun isCommentType(type: IElementType?): Boolean = type in KtTokens.COMMENTS + + override fun isBracePair(lBrace: Char, rBrace: Char): Boolean = super.isBracePair(lBrace, rBrace) || (lBrace == '[' && rBrace == ']') +} diff --git a/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLikeLangLineIndentProvider.kt b/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLikeLangLineIndentProvider.kt index af2f9ba810f..dcffbb51cff 100644 --- a/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLikeLangLineIndentProvider.kt +++ b/idea/line-indent-provider/src/org/jetbrains/kotlin/idea/formatter/lineIndent/KotlinLikeLangLineIndentProvider.kt @@ -63,11 +63,17 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider // println(debugInfo(currentPosition)) // ~~~ TESTING ~~~ - val before = currentPosition.beforeWhitespacesAndComments() + val before = currentPosition.beforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) + val after = currentPosition.afterOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) when { before.isAt(TemplateEntryOpen) -> { val baseLineOffset = before.startOffset - return factory.createIndentCalculator(Indent.getNormalIndent()) { baseLineOffset } + val indent = if (!currentPosition.hasEmptyLineAfter(offset) && after.isAt(TemplateEntryClose)) + Indent.getNoneIndent() + else + Indent.getNormalIndent() + + return factory.createIndentCalculator(indent) { baseLineOffset } } before.isAtAnyOf(TryKeyword, FinallyKeyword) -> return factory.createIndentCalculator( @@ -75,20 +81,17 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider IndentCalculator.LINE_BEFORE, ) - before.isInControlFlowStatement() -> { - val afterWhitespacesAndComments = currentPosition.afterWhitespacesAndComments() - return factory.createIndentCalculator( - when { - afterWhitespacesAndComments.isAt(LeftParenthesis) -> Indent.getContinuationIndent() - afterWhitespacesAndComments.isAtAnyOf(BlockOpeningBrace, Arrow) -> Indent.getNoneIndent() - else -> Indent.getNormalIndent() - }, - IndentCalculator.LINE_BEFORE, - ) - } + before.isInControlFlowStatement() -> return factory.createIndentCalculator( + when { + after.isAt(LeftParenthesis) -> Indent.getContinuationIndent() + after.isAtAnyOf(BlockOpeningBrace, Arrow) -> Indent.getNoneIndent() + else -> Indent.getNormalIndent() + }, + IndentCalculator.LINE_BEFORE, + ) } - currentPosition.afterWhitespacesAndComments() + after .takeIf { it.isAt(TemplateEntryClose) } ?.let { templateEntryPosition -> val indent = if (currentPosition.hasEmptyLineAfter(offset)) Indent.getNormalIndent() else Indent.getNoneIndent() @@ -100,34 +103,18 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider return null } - private fun SemanticEditorPosition.beforeWhitespacesAndComments(): SemanticEditorPosition = beforeOptionalMix( - Whitespace, - LineComment, - BlockComment, - ) - - private fun SemanticEditorPosition.afterWhitespacesAndComments(): SemanticEditorPosition = afterOptionalMix( - Whitespace, - LineComment, - BlockComment, - ) - - private fun SemanticEditorPosition.moveBeforeWhitespacesAndComments(): SemanticEditorPosition = apply { - moveBeforeOptionalMix(Whitespace, LineComment, BlockComment) - } - private fun SemanticEditorPosition.isInControlFlowStatement(): Boolean = with(copy()) { if (isAt(BlockOpeningBrace)) { moveBefore() moveBeforeParentheses(LeftParenthesis, RightParenthesis) - moveBeforeWhitespacesAndComments() + moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) } if (currElement in CONTROL_FLOW_CONSTRUCTIONS) return true if (!isAt(RightParenthesis)) return false moveBeforeParentheses(LeftParenthesis, RightParenthesis) - moveBeforeWhitespacesAndComments() + moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET) return currElement in CONTROL_FLOW_CONSTRUCTIONS } @@ -141,6 +128,7 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider FinallyKeyword, WhileKeyword, RegularStringPart, + KDoc, } companion object { @@ -150,6 +138,7 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider KtTokens.LONG_TEMPLATE_ENTRY_END to TemplateEntryClose, KtTokens.EOL_COMMENT to LineComment, KtTokens.BLOCK_COMMENT to BlockComment, + KtTokens.DOC_COMMENT to KDoc, KtTokens.ARROW to Arrow, KtTokens.LBRACE to BlockOpeningBrace, KtTokens.RBRACE to BlockClosingBrace, @@ -165,6 +154,8 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider KtTokens.DO_KEYWORD to DoKeyword, KtTokens.FOR_KEYWORD to ForKeyword, KtTokens.REGULAR_STRING_PART to RegularStringPart, + KtTokens.LBRACKET to ArrayOpeningBracket, + KtTokens.RBRACKET to ArrayClosingBracket, ) private val CONTROL_FLOW_CONSTRUCTIONS: HashSet = hashSetOf( @@ -178,5 +169,11 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider CatchKeyword, FinallyKeyword, ) + + private val WHITE_SPACE_OR_COMMENT_BIT_SET: Array = arrayOf( + Whitespace, + LineComment, + BlockComment, + ) } } \ No newline at end of file diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java index 70918c5d218..9bb082049b4 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java @@ -308,6 +308,21 @@ public class PerformanceTypingIndentationTestGenerated extends AbstractPerforman runTest("idea/testData/indentationOnNewline/InExpressionsParentheses.kt"); } + @TestMetadata("InExpressionsParentheses2.kt") + public void testInExpressionsParentheses2() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses2.kt"); + } + + @TestMetadata("InExpressionsParentheses3.kt") + public void testInExpressionsParentheses3() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses3.kt"); + } + + @TestMetadata("InExpressionsParentheses4.kt") + public void testInExpressionsParentheses4() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses4.kt"); + } + @TestMetadata("InExpressionsParenthesesBeforeOperand.kt") public void testInExpressionsParenthesesBeforeOperand() throws Exception { runTest("idea/testData/indentationOnNewline/InExpressionsParenthesesBeforeOperand.kt"); diff --git a/idea/resources/META-INF/idea.xml b/idea/resources/META-INF/idea.xml index fbec2d6780a..4ae581960ad 100644 --- a/idea/resources/META-INF/idea.xml +++ b/idea/resources/META-INF/idea.xml @@ -81,6 +81,8 @@ id="KotlinEnterHandler" order="before EnterBetweenBracesHandler"/> + diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses.after.inv.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses.after.inv.kt deleted file mode 100644 index 79f254ebab4..00000000000 --- a/idea/testData/indentationOnNewline/InExpressionsParentheses.after.inv.kt +++ /dev/null @@ -1,6 +0,0 @@ -val somelong = 3 + 4 - ( - - ) - -// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION -// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses.after.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses.after.kt index 354756743ab..f4e8d6576d1 100644 --- a/idea/testData/indentationOnNewline/InExpressionsParentheses.after.kt +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses.after.kt @@ -3,4 +3,4 @@ val somelong = 3 + 4 - ( ) // 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/idea/testData/indentationOnNewline/InExpressionsParentheses.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses.kt index 6d3f4e2c2fc..aa138e9d747 100644 --- a/idea/testData/indentationOnNewline/InExpressionsParentheses.kt +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses.kt @@ -1,4 +1,4 @@ val somelong = 3 + 4 - () // 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/idea/testData/indentationOnNewline/InExpressionsParentheses2.after.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses2.after.kt new file mode 100644 index 00000000000..c7f68c1f7d3 --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses2.after.kt @@ -0,0 +1,6 @@ +val somelong = 3 + 4 - ( + + ) + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses2.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses2.kt new file mode 100644 index 00000000000..4e0dadfe333 --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses2.kt @@ -0,0 +1,4 @@ +val somelong = 3 + 4 - () + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses3.after.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses3.after.kt new file mode 100644 index 00000000000..03f82340f39 --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses3.after.kt @@ -0,0 +1,8 @@ +fun a() { + val somelong = 3 + 4 - ( + + ) +} + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses3.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses3.kt new file mode 100644 index 00000000000..5e1af23546a --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses3.kt @@ -0,0 +1,6 @@ +fun a() { + val somelong = 3 + 4 - () +} + +// SET_FALSE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses4.after.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses4.after.kt new file mode 100644 index 00000000000..e5a9d4e8501 --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses4.after.kt @@ -0,0 +1,8 @@ +fun a() { + val somelong = 3 + 4 - ( + + ) +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/InExpressionsParentheses4.kt b/idea/testData/indentationOnNewline/InExpressionsParentheses4.kt new file mode 100644 index 00000000000..48393cc2789 --- /dev/null +++ b/idea/testData/indentationOnNewline/InExpressionsParentheses4.kt @@ -0,0 +1,6 @@ +fun a() { + val somelong = 3 + 4 - () +} + +// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION +// IGNORE_FORMATTER \ No newline at end of file diff --git a/idea/testData/indentationOnNewline/TemplateEntryOpenInMultilineString.after.kt b/idea/testData/indentationOnNewline/TemplateEntryOpenInMultilineString.after.kt index 8cf03aaa198..d0f003c1651 100644 --- a/idea/testData/indentationOnNewline/TemplateEntryOpenInMultilineString.after.kt +++ b/idea/testData/indentationOnNewline/TemplateEntryOpenInMultilineString.after.kt @@ -4,7 +4,7 @@ fun a() { select ${ - } + } from T """ } diff --git a/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java index 36ac0d8f26a..652f0b4d47a 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java @@ -310,6 +310,21 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio runTest("idea/testData/indentationOnNewline/InExpressionsParentheses.after.kt"); } + @TestMetadata("InExpressionsParentheses2.after.kt") + public void testInExpressionsParentheses2() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses2.after.kt"); + } + + @TestMetadata("InExpressionsParentheses3.after.kt") + public void testInExpressionsParentheses3() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses3.after.kt"); + } + + @TestMetadata("InExpressionsParentheses4.after.kt") + public void testInExpressionsParentheses4() throws Exception { + runTest("idea/testData/indentationOnNewline/InExpressionsParentheses4.after.kt"); + } + @TestMetadata("InExpressionsParenthesesBeforeOperand.after.kt") public void testInExpressionsParenthesesBeforeOperand() throws Exception { runTest("idea/testData/indentationOnNewline/InExpressionsParenthesesBeforeOperand.after.kt"); @@ -706,11 +721,6 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio runTest("idea/testData/indentationOnNewline/InEnumInitializerListNotEmpty.after.inv.kt"); } - @TestMetadata("InExpressionsParentheses.after.inv.kt") - public void testInExpressionsParentheses() throws Exception { - runTest("idea/testData/indentationOnNewline/InExpressionsParentheses.after.inv.kt"); - } - @TestMetadata("InExpressionsParenthesesBeforeOperand.after.inv.kt") public void testInExpressionsParenthesesBeforeOperand() throws Exception { runTest("idea/testData/indentationOnNewline/InExpressionsParenthesesBeforeOperand.after.inv.kt");