Skip to content

Commit

Permalink
De-indent the closing angle bracket of the type argument list and typ…
Browse files Browse the repository at this point in the history
…e parameter lists in ktlint_official code style (#2302)

This makes indentation of parenthesis, brackets and angle brackets consistent. E.g. in multiline format the elements of the list (excluding the closing token) are indented one indent level deep. The closing token is kept at the same indent level as the opening token.

Closes #2299
  • Loading branch information
paul-dingemans authored Oct 15, 2023
1 parent 2934538 commit d84711c
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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<K, V>
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<K, V>
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<K, V>
Expand All @@ -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)"),
Expand All @@ -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<K, V>
Expand All @@ -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)"),
Expand Down Expand Up @@ -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<String>
>
> {}
""".trimIndent()
val formattedCode =
"""
public class Foo<
Bar1 : String,
Bar2 : Map<
Int,
List<String>
>
> {}
""".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<
Expand All @@ -4529,6 +4629,7 @@ internal class IndentationRuleTest {
> {}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to codeStyleValue)
.isFormattedAs(formattedCode)
}
}
Expand Down Expand Up @@ -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()
Expand All @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ class ParameterListWrappingRuleTest {
A : GenericTypeWithALongLongALong1,
B : GenericTypeWithALongLongALong2,
C : GenericTypeWithALongLongALong3
> constructor(
> constructor(
parameterWithLongLongLongLongLongLongLongLongNameA: A,
parameterWithLongLongLongLongLongLongLongLongNameB: B,
parameterWithLongLongLongLongLongLongLongLongNameC: C
Expand Down Expand Up @@ -530,7 +530,7 @@ class ParameterListWrappingRuleTest {
public val fooBar: List<
Foo,
Bar
>,
>,
)
""".trimIndent()
parameterListWrappingRuleAssertThat(code).hasNoLintViolations()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ class SpacingAroundAngleBracketsRuleTest {
val c: Map <Int, String> = mapOf()
val d: Map<
Int, String
> = mapOf()
> = mapOf()
val e: Map<
Int,
String
> = mapOf()
> = mapOf()
val f: Map
<
Int,
Expand All @@ -31,8 +31,8 @@ class SpacingAroundAngleBracketsRuleTest {
Int,
List<
String
>
> = mapOf()
>
> = mapOf()
""".trimIndent()
val formattedCode =
"""
Expand All @@ -41,22 +41,22 @@ class SpacingAroundAngleBracketsRuleTest {
val c: Map<Int, String> = 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<Int, List<String>> = mapOf()
val h: Map<
Int,
List<
String
>
> = mapOf()
>
> = mapOf()
""".trimIndent()
spacingAroundAngleBracketsRuleAssertThat(code)
.addAdditionalRuleProvider { IndentationRule() }
Expand Down Expand Up @@ -89,8 +89,8 @@ class SpacingAroundAngleBracketsRuleTest {
Bar2 : Map<
Int,
List< String >
>
> {}
>
> {}
""".trimIndent()
val formattedCode =
"""
Expand All @@ -105,8 +105,8 @@ class SpacingAroundAngleBracketsRuleTest {
Bar2 : Map<
Int,
List<String>
>
> {}
>
> {}
""".trimIndent()
spacingAroundAngleBracketsRuleAssertThat(code)
.addAdditionalRuleProvider { IndentationRule() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class TrailingCommaOnCallSiteRuleTest {
val list1: List<String,> = 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()
Expand All @@ -149,10 +149,10 @@ class TrailingCommaOnCallSiteRuleTest {
val list1: List<String> = 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)
Expand All @@ -170,20 +170,20 @@ class TrailingCommaOnCallSiteRuleTest {
val list1: List<String> = 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<String> = 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)
Expand Down
Loading

0 comments on commit d84711c

Please sign in to comment.