diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRule.kt index 375f44e75b..300d60d495 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRule.kt @@ -265,9 +265,19 @@ public class IndentationRule : startIndentContext(node) } + node.elementType == TYPE_ARGUMENT_LIST || + node.elementType == TYPE_PARAMETER_LIST -> + if (codeStyle == ktlint_official) { + // Contrary to the IntelliJ IDEA default formatter, do not indent the closing angle bracket + startIndentContext( + fromAstNode = node, + lastChildIndent = "", + ) + } else { + startIndentContext(node) + } + node.elementType == BINARY_WITH_TYPE || - node.elementType == TYPE_ARGUMENT_LIST || - node.elementType == TYPE_PARAMETER_LIST || node.elementType == USER_TYPE -> startIndentContext(node) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/AnnotationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/AnnotationRuleTest.kt index ae3d1509bd..ab4813140f 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/AnnotationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/AnnotationRuleTest.kt @@ -739,7 +739,7 @@ class AnnotationRuleTest { @Bar("bar") @Foo String - > = FooBar() + > = FooBar() """.trimIndent() @Suppress("ktlint:standard:argument-list-wrapping", "ktlint:standard:max-line-length") annotationRuleAssertThat(code) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRuleTest.kt index 94efec9dc5..42a81f7450 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/IndentationRuleTest.kt @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource import org.junit.jupiter.params.provider.ValueSource @Suppress("RemoveCurlyBracesFromTemplate") @@ -974,7 +975,65 @@ internal class IndentationRuleTest { """.trimIndent() @Test - fun `Given a class declaration implementing a super type with generics`() { + fun `Given ktlint-official code style and a class declaration implementing a super type with generics`() { + val formattedCode = + """ + open class Foo + class Bar + class FooBar : + Foo< + String, + Int + >, + Bar() { + } + """.trimIndent() + indentationRuleAssertThat(code) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official) + .hasLintViolations( + LintViolation(4, 1, "Unexpected indentation (0) (should be 4)"), + LintViolation(5, 1, "Unexpected indentation (0) (should be 8)"), + LintViolation(6, 1, "Unexpected indentation (0) (should be 8)"), + LintViolation(7, 1, "Unexpected indentation (0) (should be 4)"), + LintViolation(8, 1, "Unexpected indentation (0) (should be 4)"), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given ktlint-official code style and a class declaration implementing a super type with generics (tab indentation)`() { + val formattedCode = + """ + open class Foo + class Bar + class FooBar : + ${TAB}Foo< + ${TAB}${TAB}String, + ${TAB}${TAB}Int + ${TAB}>, + ${TAB}Bar() { + } + """.trimIndent() + indentationRuleAssertThat(code) + .withEditorConfigOverride(INDENT_STYLE_TAB) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official) + .hasLintViolations( + LintViolation(4, 1, "Unexpected indentation (0) (should be 1)"), + LintViolation(5, 1, "Unexpected indentation (0) (should be 2)"), + LintViolation(6, 1, "Unexpected indentation (0) (should be 2)"), + LintViolation(7, 1, "Unexpected indentation (0) (should be 1)"), + LintViolation(8, 1, "Unexpected indentation (0) (should be 1)"), + ).isFormattedAs(formattedCode) + } + + @ParameterizedTest(name = "CodeStyle: {0}") + @EnumSource( + value = CodeStyleValue::class, + mode = EnumSource.Mode.EXCLUDE, + names = ["ktlint_official"], + ) + fun `Given non-ktlint-official code style and a class declaration implementing a super type with generics`( + codeStyleValue: CodeStyleValue, + ) { val formattedCode = """ open class Foo @@ -988,6 +1047,7 @@ internal class IndentationRuleTest { } """.trimIndent() indentationRuleAssertThat(code) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to codeStyleValue) .hasLintViolations( LintViolation(4, 1, "Unexpected indentation (0) (should be 4)"), LintViolation(5, 1, "Unexpected indentation (0) (should be 8)"), @@ -997,8 +1057,15 @@ internal class IndentationRuleTest { ).isFormattedAs(formattedCode) } - @Test - fun `Given a class declaration implementing a super type with generics (tab indentation)`() { + @ParameterizedTest(name = "CodeStyle: {0}") + @EnumSource( + value = CodeStyleValue::class, + mode = EnumSource.Mode.EXCLUDE, + names = ["ktlint_official"], + ) + fun `Given non-ktlint-official code style and a class declaration implementing a super type with generics (tab indentation)`( + codeStyleValue: CodeStyleValue, + ) { val formattedCode = """ open class Foo @@ -1013,6 +1080,7 @@ internal class IndentationRuleTest { """.trimIndent() indentationRuleAssertThat(code) .withEditorConfigOverride(INDENT_STYLE_TAB) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to codeStyleValue) .hasLintViolations( LintViolation(4, 1, "Unexpected indentation (0) (should be 1)"), LintViolation(5, 1, "Unexpected indentation (0) (should be 2)"), @@ -4507,7 +4575,39 @@ internal class IndentationRuleTest { } @Test - fun `Given a nested type parameter list`() { + fun `Given ktlint-official code style and a nested type parameter list`() { + val code = + """ + public class Foo< + Bar1 : String, + Bar2 : Map< + Int, + List + > + > {} + """.trimIndent() + val formattedCode = + """ + public class Foo< + Bar1 : String, + Bar2 : Map< + Int, + List + > + > {} + """.trimIndent() + indentationRuleAssertThat(code) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official) + .isFormattedAs(formattedCode) + } + + @ParameterizedTest(name = "CodeStyle: {0}") + @EnumSource( + value = CodeStyleValue::class, + mode = EnumSource.Mode.EXCLUDE, + names = ["ktlint_official"], + ) + fun `Given non-ktlint-official code style and a nested type parameter list`(codeStyleValue: CodeStyleValue) { val code = """ public class Foo< @@ -4529,6 +4629,7 @@ internal class IndentationRuleTest { > {} """.trimIndent() indentationRuleAssertThat(code) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to codeStyleValue) .isFormattedAs(formattedCode) } } @@ -4844,15 +4945,13 @@ internal class IndentationRuleTest { ) fun fooBar() """.trimIndent() - // Actually, the closing ">" should be de-indented in same way as is done with ")", "]" and "}". It is - // however indented to keep it in sync with other TYPE_ARGUMENT_LISTs which are formatted in this way. val formattedCode = """ context( FooBar< Foo, Bar - > + > ) fun fooBar() """.trimIndent() @@ -4861,7 +4960,7 @@ internal class IndentationRuleTest { LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"), LintViolation(3, 1, "Unexpected indentation (0) (should be 8)"), LintViolation(4, 1, "Unexpected indentation (0) (should be 8)"), - LintViolation(5, 1, "Unexpected indentation (0) (should be 8)"), + LintViolation(5, 1, "Unexpected indentation (0) (should be 4)"), ).isFormattedAs(formattedCode) } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ParameterListWrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ParameterListWrappingRuleTest.kt index 94aac3ea93..5bdb043133 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ParameterListWrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ParameterListWrappingRuleTest.kt @@ -498,7 +498,7 @@ class ParameterListWrappingRuleTest { A : GenericTypeWithALongLongALong1, B : GenericTypeWithALongLongALong2, C : GenericTypeWithALongLongALong3 - > constructor( + > constructor( parameterWithLongLongLongLongLongLongLongLongNameA: A, parameterWithLongLongLongLongLongLongLongLongNameB: B, parameterWithLongLongLongLongLongLongLongLongNameC: C @@ -530,7 +530,7 @@ class ParameterListWrappingRuleTest { public val fooBar: List< Foo, Bar - >, + >, ) """.trimIndent() parameterListWrappingRuleAssertThat(code).hasNoLintViolations() diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundAngleBracketsRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundAngleBracketsRuleTest.kt index 6971019fe1..84aa1c3e3c 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundAngleBracketsRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundAngleBracketsRuleTest.kt @@ -16,11 +16,11 @@ class SpacingAroundAngleBracketsRuleTest { val c: Map = mapOf() val d: Map< Int, String - > = mapOf() + > = mapOf() val e: Map< Int, String - > = mapOf() + > = mapOf() val f: Map < Int, @@ -31,8 +31,8 @@ class SpacingAroundAngleBracketsRuleTest { Int, List< String - > - > = mapOf() + > + > = mapOf() """.trimIndent() val formattedCode = """ @@ -41,22 +41,22 @@ class SpacingAroundAngleBracketsRuleTest { val c: Map = mapOf() val d: Map< Int, String - > = mapOf() + > = mapOf() val e: Map< Int, String - > = mapOf() + > = mapOf() val f: Map< Int, String - > = mapOf() + > = mapOf() val g: Map> = mapOf() val h: Map< Int, List< String - > - > = mapOf() + > + > = mapOf() """.trimIndent() spacingAroundAngleBracketsRuleAssertThat(code) .addAdditionalRuleProvider { IndentationRule() } @@ -89,8 +89,8 @@ class SpacingAroundAngleBracketsRuleTest { Bar2 : Map< Int, List< String > - > - > {} + > + > {} """.trimIndent() val formattedCode = """ @@ -105,8 +105,8 @@ class SpacingAroundAngleBracketsRuleTest { Bar2 : Map< Int, List - > - > {} + > + > {} """.trimIndent() spacingAroundAngleBracketsRuleAssertThat(code) .addAdditionalRuleProvider { IndentationRule() } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnCallSiteRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnCallSiteRuleTest.kt index da13fd95cb..ab974300b3 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnCallSiteRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnCallSiteRuleTest.kt @@ -139,7 +139,7 @@ class TrailingCommaOnCallSiteRuleTest { val list1: List = emptyList() val list2: List< String, // The comma before the comment should be removed without removing the comment itself - > = emptyList() + > = emptyList() val list3: List< String, /* The comma before the comment should be removed without removing the comment itself */ > = emptyList() @@ -149,10 +149,10 @@ class TrailingCommaOnCallSiteRuleTest { val list1: List = emptyList() val list2: List< String // The comma before the comment should be removed without removing the comment itself - > = emptyList() + > = emptyList() val list3: List< String /* The comma before the comment should be removed without removing the comment itself */ - > = emptyList() + > = emptyList() """.trimIndent() trailingCommaOnCallSiteRuleAssertThat(code) .withEditorConfigOverride(TRAILING_COMMA_ON_CALL_SITE_PROPERTY to false) @@ -170,20 +170,20 @@ class TrailingCommaOnCallSiteRuleTest { val list1: List = emptyList() val list2: List< String // The comma should be inserted before the comment - > = emptyList() + > = emptyList() val list3: List< String /* The comma should be inserted before the comment */ - > = emptyList() + > = emptyList() """.trimIndent() val formattedCode = """ val list1: List = emptyList() val list2: List< String, // The comma should be inserted before the comment - > = emptyList() + > = emptyList() val list3: List< String, /* The comma should be inserted before the comment */ - > = emptyList() + > = emptyList() """.trimIndent() trailingCommaOnCallSiteRuleAssertThat(code) .withEditorConfigOverride(TRAILING_COMMA_ON_CALL_SITE_PROPERTY to true) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnDeclarationSiteRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnDeclarationSiteRuleTest.kt index 93aee4bdec..5998046ed7 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnDeclarationSiteRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TrailingCommaOnDeclarationSiteRuleTest.kt @@ -146,11 +146,11 @@ class TrailingCommaOnDeclarationSiteRuleTest { class Foo2< A, B, // The comma before the comment should be removed without removing the comment itself - > {} + > {} class Foo3< A, B, /* The comma before the comment should be removed without removing the comment itself */ - > {} + > {} """.trimIndent() val formattedCode = """ @@ -158,11 +158,11 @@ class TrailingCommaOnDeclarationSiteRuleTest { class Foo2< A, B // The comma before the comment should be removed without removing the comment itself - > {} + > {} class Foo3< A, B /* The comma before the comment should be removed without removing the comment itself */ - > {} + > {} """.trimIndent() trailingCommaOnDeclarationSiteRuleAssertThat(code) .withEditorConfigOverride(TRAILING_COMMA_ON_DECLARATION_SITE_PROPERTY to false) @@ -181,11 +181,11 @@ class TrailingCommaOnDeclarationSiteRuleTest { class Foo2< A, B // The comma should be inserted before the comment - > {} + > {} class Foo3< A, B /* The comma should be inserted before the comment */ - > {} + > {} """.trimIndent() val formattedCode = """ @@ -193,11 +193,11 @@ class TrailingCommaOnDeclarationSiteRuleTest { class Foo2< A, B, // The comma should be inserted before the comment - > {} + > {} class Foo3< A, B, /* The comma should be inserted before the comment */ - > {} + > {} """.trimIndent() trailingCommaOnDeclarationSiteRuleAssertThat(code) .withEditorConfigOverride(TRAILING_COMMA_ON_DECLARATION_SITE_PROPERTY to true)