LineIndentProvider: fix for do-while

Part of #KT-22211
This commit is contained in:
Dmitry Gridin
2020-06-04 13:26:21 +07:00
parent 7a58a59114
commit acc15e5fad
17 changed files with 178 additions and 16 deletions
@@ -80,43 +80,68 @@ abstract class KotlinLikeLangLineIndentProvider : JavaLikeLangLineIndentProvider
Indent.getNoneIndent(),
IndentCalculator.LINE_BEFORE,
)
}
before.isInControlFlowStatement() -> return factory.createIndentCalculator(
before.controlFlowStatementBefore()?.let { controlFlowKeywordPosition ->
return factory.createIndentCalculator(
when {
after.isAt(LeftParenthesis) -> Indent.getContinuationIndent()
after.isAtAnyOf(BlockOpeningBrace, Arrow) -> Indent.getNoneIndent()
after.isAtAnyOf(BlockOpeningBrace, Arrow) || controlFlowKeywordPosition.isWhileInsideDoWhile() -> Indent.getNoneIndent()
else -> Indent.getNormalIndent()
},
IndentCalculator.LINE_BEFORE,
)
}
after
.takeIf { it.isAt(TemplateEntryClose) }
?.let { templateEntryPosition ->
val indent = if (currentPosition.hasEmptyLineAfter(offset)) Indent.getNormalIndent() else Indent.getNoneIndent()
templateEntryPosition.moveBeforeParentheses(TemplateEntryOpen, TemplateEntryClose)
val baseLineOffset = templateEntryPosition.startOffset
return factory.createIndentCalculator(indent) { baseLineOffset }
}
after.takeIf { it.isAt(TemplateEntryClose) }?.let { templateEntryPosition ->
val indent = if (currentPosition.hasEmptyLineAfter(offset)) Indent.getNormalIndent() else Indent.getNoneIndent()
templateEntryPosition.moveBeforeParentheses(TemplateEntryOpen, TemplateEntryClose)
val baseLineOffset = templateEntryPosition.startOffset
return factory.createIndentCalculator(indent) { baseLineOffset }
}
return null
}
private fun SemanticEditorPosition.isInControlFlowStatement(): Boolean = with(copy()) {
private fun SemanticEditorPosition.moveBeforeIfThisIsWhiteSpaceOrComment() = moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET)
private fun SemanticEditorPosition.isWhileInsideDoWhile(): Boolean {
if (!isAt(WhileKeyword)) return false
with(copy()) {
moveBefore()
var whileKeywordLevel = 1
while (!isAtEnd) when {
isAt(BlockOpeningBrace) -> return false
isAt(DoKeyword) -> {
if (--whileKeywordLevel == 0) return true
moveBefore()
}
isAt(WhileKeyword) -> {
++whileKeywordLevel
moveBefore()
}
isAt(BlockClosingBrace) -> moveBeforeParentheses(BlockOpeningBrace, BlockClosingBrace)
else -> moveBefore()
}
}
return false
}
private fun SemanticEditorPosition.controlFlowStatementBefore(): SemanticEditorPosition? = with(copy()) {
if (isAt(BlockOpeningBrace)) {
moveBefore()
moveBeforeParentheses(LeftParenthesis, RightParenthesis)
moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET)
moveBeforeIfThisIsWhiteSpaceOrComment()
}
if (currElement in CONTROL_FLOW_CONSTRUCTIONS) return true
if (!isAt(RightParenthesis)) return false
if (currElement in CONTROL_FLOW_CONSTRUCTIONS) return this
if (!isAt(RightParenthesis)) return null
moveBeforeParentheses(LeftParenthesis, RightParenthesis)
moveBeforeOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET)
moveBeforeIfThisIsWhiteSpaceOrComment()
return currElement in CONTROL_FLOW_CONSTRUCTIONS
return takeIf { currElement in CONTROL_FLOW_CONSTRUCTIONS }
}
enum class KotlinElement : SemanticEditorPosition.SyntaxElement {
@@ -118,6 +118,41 @@ public class PerformanceTypingIndentationTestGenerated extends AbstractPerforman
runTest("idea/testData/indentationOnNewline/DoInFun.kt");
}
@TestMetadata("DoWhile.kt")
public void testDoWhile() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile.kt");
}
@TestMetadata("DoWhile2.kt")
public void testDoWhile2() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile2.kt");
}
@TestMetadata("DoWhile3.kt")
public void testDoWhile3() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile3.kt");
}
@TestMetadata("DoWhile4.kt")
public void testDoWhile4() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile4.kt");
}
@TestMetadata("DoWhile5.kt")
public void testDoWhile5() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile5.kt");
}
@TestMetadata("DoWhile6.kt")
public void testDoWhile6() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile6.kt");
}
@TestMetadata("DoWhile7.kt")
public void testDoWhile7() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile7.kt");
}
@TestMetadata("DoWithBraces.kt")
public void testDoWithBraces() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWithBraces.kt");
+4
View File
@@ -0,0 +1,4 @@
fun some() {
do println() while (true)
<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun some() {
do println() while (true)<caret>
}
+4
View File
@@ -0,0 +1,4 @@
fun some() {
do do println() while (true) while (true)
<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun some() {
do do println() while (true) while (true)<caret>
}
+6
View File
@@ -0,0 +1,6 @@
fun some() {
do {
while (true) println()
} while (true)
<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun some() {
do {
while (true) println()
} while (true)<caret>
}
+4
View File
@@ -0,0 +1,4 @@
fun some() {
while (true)
<caret>
}
+3
View File
@@ -0,0 +1,3 @@
fun some() {
while (true)<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun some() {
while (true)
while (true)
<caret>
}
+4
View File
@@ -0,0 +1,4 @@
fun some() {
while (true)
while (true)<caret>
}
+8
View File
@@ -0,0 +1,8 @@
fun some() {
while (true) {
println()
}
while (true)
<caret>
}
+7
View File
@@ -0,0 +1,7 @@
fun some() {
while (true) {
println()
}
while (true)<caret>
}
+6
View File
@@ -0,0 +1,6 @@
fun some() {
do println() while (true)
println()
while (true)
<caret>
}
+5
View File
@@ -0,0 +1,5 @@
fun some() {
do println() while (true)
println()
while (true)<caret>
}
@@ -120,6 +120,41 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
runTest("idea/testData/indentationOnNewline/DoInFun.after.kt");
}
@TestMetadata("DoWhile.after.kt")
public void testDoWhile() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile.after.kt");
}
@TestMetadata("DoWhile2.after.kt")
public void testDoWhile2() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile2.after.kt");
}
@TestMetadata("DoWhile3.after.kt")
public void testDoWhile3() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile3.after.kt");
}
@TestMetadata("DoWhile4.after.kt")
public void testDoWhile4() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile4.after.kt");
}
@TestMetadata("DoWhile5.after.kt")
public void testDoWhile5() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile5.after.kt");
}
@TestMetadata("DoWhile6.after.kt")
public void testDoWhile6() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile6.after.kt");
}
@TestMetadata("DoWhile7.after.kt")
public void testDoWhile7() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWhile7.after.kt");
}
@TestMetadata("DoWithBraces.after.kt")
public void testDoWithBraces() throws Exception {
runTest("idea/testData/indentationOnNewline/DoWithBraces.after.kt");