[formatter] line indent provider: fix indent for empty braces

^KT-42411 Fixed
This commit is contained in:
Dmitry Gridin
2020-10-02 19:49:15 +07:00
parent 380226cba0
commit 3078bd7b67
21 changed files with 247 additions and 50 deletions
@@ -46,13 +46,20 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() {
when {
after.isAt(BlockClosingBrace) && !currentPosition.hasLineBreaksAfter(offset) ->
return factory.createIndentCalculatorForBrace(before, after, BlockOpeningBrace, BlockClosingBrace)
return factory.createIndentCalculatorForBrace(before, after, BlockOpeningBrace, BlockClosingBrace, Indent.getNoneIndent())
before.isAt(BlockOpeningBrace) && after.isAt(BlockClosingBrace) ->
return factory.createIndentCalculator(Indent.getNormalIndent(), before.startOffset)
before.isAt(BlockOpeningBrace) && after.isAt(BlockClosingBrace) -> {
return factory.createIndentCalculatorForBrace(before, after, BlockOpeningBrace, BlockClosingBrace, Indent.getNormalIndent())
}
after.isAt(ArrayClosingBracket) && !currentPosition.hasLineBreaksAfter(offset) ->
return factory.createIndentCalculatorForBrace(before, after, ArrayOpeningBracket, ArrayClosingBracket)
return factory.createIndentCalculatorForBrace(
before,
after,
ArrayOpeningBracket,
ArrayClosingBracket,
Indent.getNoneIndent()
)
before.isAt(ArrayOpeningBracket) && after.isAt(ArrayClosingBracket) -> {
val indent = if (isSimilarToFunctionInvocation(before))
@@ -63,18 +70,15 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() {
return factory.createIndentCalculator(indent, before.startOffset)
}
before.isAt(BlockOpeningBrace) && before.beforeIgnoringWhiteSpaceOrComment().isFunctionDeclaration() ->
return factory.createIndentCalculator(Indent.getNormalIndent(), before.startOffset)
// KT-39716
// after.isAt(Quest) && after.after().isAt(Colon) -> {
// val indent = if (settings.continuationIndentInElvis)
// Indent.getContinuationIndent()
// else
// Indent.getNormalIndent()
//
// return factory.createIndentCalculator(indent, before.startOffset)
// }
// KT-39716
// after.isAt(Quest) && after.after().isAt(Colon) -> {
// val indent = if (settings.continuationIndentInElvis)
// Indent.getContinuationIndent()
// else
// Indent.getNormalIndent()
//
// return factory.createIndentCalculator(indent, before.startOffset)
// }
before.isAt(Colon) && before.before().isAt(Quest) ->
return factory.createIndentCalculator(Indent.getNoneIndent(), before.startOffset)
@@ -214,18 +218,27 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() {
before: SemanticEditorPosition,
after: SemanticEditorPosition,
leftBraceType: SemanticEditorPosition.SyntaxElement,
rightBraceType: SemanticEditorPosition.SyntaxElement
): IndentCalculator? {
rightBraceType: SemanticEditorPosition.SyntaxElement,
defaultIndent: Indent
): IndentCalculator {
val leftBrace = before.copyAnd {
it.moveToLeftParenthesisBackwardsSkippingNested(leftBraceType, rightBraceType)
}
val indent = if (after.after().afterOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET).isAt(Comma))
createAlignMultilineIndent(leftBrace)
else
Indent.getNoneIndent()
if (after.after().afterOptionalMix(*WHITE_SPACE_OR_COMMENT_BIT_SET).isAt(Comma)) {
return createIndentCalculator(createAlignMultilineIndent(leftBrace), leftBrace.startOffset)
}
return createIndentCalculator(indent, leftBrace.startOffset)
val beforeLeftBrace = leftBrace.copyAnd { it.moveBeforeIgnoringWhiteSpaceOrComment() }
val leftAnchor = if (beforeLeftBrace.isAt(RightParenthesis)) {
beforeLeftBrace.moveBeforeParentheses(LeftParenthesis, RightParenthesis)
beforeLeftBrace
} else {
findFunctionDeclarationBeforeBody(beforeLeftBrace)
}
val resultPosition = leftAnchor?.takeIf { !it.isAtEnd } ?: leftBrace
return createIndentCalculator(defaultIndent, resultPosition.startOffset)
}
private fun IndentCalculatorFactory.createIndentCalculatorForParenthesis(
@@ -274,11 +287,6 @@ abstract class KotlinLangLineIndentProvider : JavaLikeLangLineIndentProvider() {
return null
}
/**
* @receiver is position before '=' for expression body or '{' for block body
*/
private fun SemanticEditorPosition.isFunctionDeclaration(): Boolean = findFunctionDeclarationBeforeBody(this) != null
/**
* @param endOfDeclaration is position before '=' for expression body or '{' for block body
*/
@@ -93,16 +93,6 @@ public class PerformanceTypingIndentationTestGenerated extends AbstractPerforman
runTest("idea/testData/indentationOnNewline/ConsecutiveCallsInSafeCallsEnd.kt");
}
@TestMetadata("FunctionBlock.kt")
public void testFunctionBlock() throws Exception {
runTest("idea/testData/indentationOnNewline/FunctionBlock.kt");
}
@TestMetadata("FunctionBlock2.kt")
public void testFunctionBlock2() throws Exception {
runTest("idea/testData/indentationOnNewline/FunctionBlock2.kt");
}
@TestMetadata("HigherOrderFunction.kt")
public void testHigherOrderFunction() throws Exception {
runTest("idea/testData/indentationOnNewline/HigherOrderFunction.kt");
@@ -567,6 +557,64 @@ public class PerformanceTypingIndentationTestGenerated extends AbstractPerforman
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyBraces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EmptyBraces extends AbstractPerformanceTypingIndentationTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doPerfTest, this, testDataFilePath);
}
public void testAllFilesPresentInEmptyBraces() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/indentationOnNewline/emptyBraces"), Pattern.compile("^([^.]+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("ClassWithConstructor.kt")
public void testClassWithConstructor() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithConstructor.kt");
}
@TestMetadata("ClassWithConstructor2.kt")
public void testClassWithConstructor2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithConstructor2.kt");
}
@TestMetadata("ClassWithoutConstructor.kt")
public void testClassWithoutConstructor() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithoutConstructor.kt");
}
@TestMetadata("FunctionBlock.kt")
public void testFunctionBlock() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBlock.kt");
}
@TestMetadata("FunctionBlock2.kt")
public void testFunctionBlock2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBlock2.kt");
}
@TestMetadata("FunctionBody3.kt")
public void testFunctionBody3() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBody3.kt");
}
@TestMetadata("FunctionBody4.kt")
public void testFunctionBody4() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBody4.kt");
}
@TestMetadata("FunctionBodyInsideClass.kt")
public void testFunctionBodyInsideClass() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBodyInsideClass.kt");
}
@TestMetadata("FunctionBodyInsideClass2.kt")
public void testFunctionBodyInsideClass2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBodyInsideClass2.kt");
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyParameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,3 @@
class A() {
<caret>
}
@@ -0,0 +1 @@
class A() {<caret>}
@@ -0,0 +1,5 @@
// IGNORE_FORMATTER
class A(a: Int,
b: Int) {
<caret>
}
@@ -0,0 +1,3 @@
// IGNORE_FORMATTER
class A(a: Int,
b: Int) {<caret>}
@@ -0,0 +1,3 @@
class A {
<caret>
}
@@ -0,0 +1 @@
class A {<caret>}
@@ -6,4 +6,4 @@ fun main(args: Array<String>) {
times(3) {
<caret>
}
}
}
@@ -4,4 +4,4 @@ private fun <T> times(times : Int, body : () -> T) {}
fun main(args: Array<String>) {
times(3) {<caret>}
}
}
@@ -0,0 +1,7 @@
// IGNORE_FORMATTER
fun getLibraryModule(symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean): SwiftModule {
<caret>
}
@@ -0,0 +1,5 @@
// IGNORE_FORMATTER
fun getLibraryModule(symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean): SwiftModule {<caret>}
@@ -0,0 +1,9 @@
// IGNORE_FORMATTER
fun getLibraryModule(
symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean
): SwiftModule {
<caret>
}
@@ -0,0 +1,7 @@
// IGNORE_FORMATTER
fun getLibraryModule(
symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean
): SwiftModule { <caret> }
@@ -0,0 +1,9 @@
// IGNORE_FORMATTER
class A {
fun getLibraryModule(symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean): SwiftModule {
<caret>
}
}
@@ -0,0 +1,7 @@
// IGNORE_FORMATTER
class A {
fun getLibraryModule(symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean): SwiftModule { <caret> }
}
@@ -0,0 +1,11 @@
// IGNORE_FORMATTER
class A {
fun getLibraryModule(
symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean
): SwiftModule {
<caret>
}
}
@@ -0,0 +1,9 @@
// IGNORE_FORMATTER
class A {
fun getLibraryModule(
symbol: ModuleMapSymbol,
headersSearchRoot: HeadersSearchRoot,
configuration: OCResolveConfiguration,
isRootUpToDate: Boolean
): SwiftModule { <caret> }
}
@@ -95,16 +95,6 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
runTest("idea/testData/indentationOnNewline/ConsecutiveCallsInSafeCallsEnd.after.kt");
}
@TestMetadata("FunctionBlock.after.kt")
public void testFunctionBlock() throws Exception {
runTest("idea/testData/indentationOnNewline/FunctionBlock.after.kt");
}
@TestMetadata("FunctionBlock2.after.kt")
public void testFunctionBlock2() throws Exception {
runTest("idea/testData/indentationOnNewline/FunctionBlock2.after.kt");
}
@TestMetadata("HigherOrderFunction.after.kt")
public void testHigherOrderFunction() throws Exception {
runTest("idea/testData/indentationOnNewline/HigherOrderFunction.after.kt");
@@ -569,6 +559,64 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyBraces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EmptyBraces extends AbstractTypingIndentationTestBase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doNewlineTest, this, testDataFilePath);
}
public void testAllFilesPresentInEmptyBraces() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/indentationOnNewline/emptyBraces"), Pattern.compile("^([^\\.]+)\\.after\\.kt.*$"), null, true);
}
@TestMetadata("ClassWithConstructor.after.kt")
public void testClassWithConstructor() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithConstructor.after.kt");
}
@TestMetadata("ClassWithConstructor2.after.kt")
public void testClassWithConstructor2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithConstructor2.after.kt");
}
@TestMetadata("ClassWithoutConstructor.after.kt")
public void testClassWithoutConstructor() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/ClassWithoutConstructor.after.kt");
}
@TestMetadata("FunctionBlock.after.kt")
public void testFunctionBlock() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBlock.after.kt");
}
@TestMetadata("FunctionBlock2.after.kt")
public void testFunctionBlock2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBlock2.after.kt");
}
@TestMetadata("FunctionBody3.after.kt")
public void testFunctionBody3() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBody3.after.kt");
}
@TestMetadata("FunctionBody4.after.kt")
public void testFunctionBody4() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBody4.after.kt");
}
@TestMetadata("FunctionBodyInsideClass.after.kt")
public void testFunctionBodyInsideClass() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBodyInsideClass.after.kt");
}
@TestMetadata("FunctionBodyInsideClass2.after.kt")
public void testFunctionBodyInsideClass2() throws Exception {
runTest("idea/testData/indentationOnNewline/emptyBraces/FunctionBodyInsideClass2.after.kt");
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyParameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1346,6 +1394,19 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyBraces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EmptyBraces extends AbstractTypingIndentationTestBase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doNewlineTestWithInvert, this, testDataFilePath);
}
public void testAllFilesPresentInEmptyBraces() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/indentationOnNewline/emptyBraces"), Pattern.compile("^([^\\.]+)\\.after\\.inv\\.kt.*$"), null, true);
}
}
@TestMetadata("idea/testData/indentationOnNewline/emptyParameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)