Skip to content

Commit

Permalink
Do not indent class body for classes having a long super type list in…
Browse files Browse the repository at this point in the history
… code style `ktlint_official` as it is inconsistent compared to other class bodies `indent` (#2116)

Closes #2115
  • Loading branch information
paul-dingemans committed Jul 7, 2023
1 parent 5fd06a2 commit 1e0773f
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 65 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Fixed

* Do not indent class body for classes having a long super type list in code style `ktlint_official` as it is inconsistent compared to other class bodies `indent` [#2115](https://github.com/pinterest/ktlint/issues/2115)

### Changed

* Update dependency gradle to v8.2 ([#2105](https://github.com/pinterest/ktlint/pull/2105))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.CLOSING_QUOTE
import com.pinterest.ktlint.rule.engine.core.api.ElementType.COLON
import com.pinterest.ktlint.rule.engine.core.api.ElementType.CONDITION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.CONSTRUCTOR_DELEGATION_CALL
import com.pinterest.ktlint.rule.engine.core.api.ElementType.CONSTRUCTOR_KEYWORD
import com.pinterest.ktlint.rule.engine.core.api.ElementType.CONTEXT_RECEIVER_LIST
import com.pinterest.ktlint.rule.engine.core.api.ElementType.DELEGATED_SUPER_TYPE_ENTRY
import com.pinterest.ktlint.rule.engine.core.api.ElementType.DESTRUCTURING_DECLARATION
Expand Down Expand Up @@ -605,12 +606,17 @@ public class IndentationRule :
}

val primaryConstructor = node.findChildByType(PRIMARY_CONSTRUCTOR)
if (codeStyle == ktlint_official && primaryConstructor != null) {
val containsConstructorKeyword = primaryConstructor?.findChildByType(CONSTRUCTOR_KEYWORD) != null
if (codeStyle == ktlint_official && primaryConstructor != null && containsConstructorKeyword) {
// Indent both constructor and super type list
nextToAstNode =
startIndentContext(
fromAstNode = primaryConstructor.getPrecedingLeadingCommentsAndWhitespaces(),
toAstNode = nextToAstNode,
toAstNode =
node
.findChildByType(SUPER_TYPE_LIST)
?.lastChildLeafOrSelf()
?: nextToAstNode,
).prevCodeLeaf()
} else {
node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4958,62 +4958,50 @@ internal class IndentationRuleTest {
indentationRuleAssertThat(code).hasNoLintViolations()
}

@Test
fun `Issue 1916 - Given a class declaration with an annotation before the constructor`() {
val code =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) {
fun foo() = "foo"
}
""".trimIndent()
val formattedCode =
"""
class Foo
@Nested
inner class `Issue 1916, issue 2115 - Given the ktlint_official code style and a class declaration with an annotated constructor` {
@Test
fun `Issue 1916, issue 2115 - Given a class declaration with an annotation before the constructor keyword`() {
val code =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) {
fun foo() = "foo"
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasLintViolations(
LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(3, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(5, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(6, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(7, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(8, 1, "Unexpected indentation (0) (should be 4)"),
).isFormattedAs(formattedCode)
}
""".trimIndent()
val formattedCode =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) {
fun foo() = "foo"
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasLintViolations(
LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(3, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(5, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(6, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(7, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(8, 1, "Unexpected indentation (0) (should be 4)"),
).isFormattedAs(formattedCode)
}

@Test
fun `Issue 1916 - Given a class declaration with an annotation before the constructor nad having a super type list`() {
val code =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) : Foobar(
"foobar1",
"foobar2",
) {
fun foo() = "foo"
}
""".trimIndent()
val formattedCode =
"""
class Foo
@Test
fun `Issue 1916, issue 2115 - Given a class declaration with an annotation before the constructor and having a single super type`() {
val code =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
Expand All @@ -5024,21 +5012,96 @@ internal class IndentationRuleTest {
) {
fun foo() = "foo"
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasLintViolations(
LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(3, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(5, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(6, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(7, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(8, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(9, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(10, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(11, 1, "Unexpected indentation (0) (should be 4)"),
).isFormattedAs(formattedCode)
""".trimIndent()
val formattedCode =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) : Foobar(
"foobar1",
"foobar2",
) {
fun foo() = "foo"
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasLintViolations(
LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(3, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(5, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(6, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(7, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(8, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(9, 1, "Unexpected indentation (0) (should be 4)"),
).isFormattedAs(formattedCode)
}

@Test
fun `Issue 1916, issue 2115 - Given a class declaration with an annotation before the constructor and having multiple super types`() {
val code =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) : Foobar1(
"foobar1",
"foobar2",
), FooBar2 {
fun foo() = "foo"
}
""".trimIndent()
val formattedCode =
"""
class Foo
@Bar1 @Bar2
constructor(
foo1: Foo1,
foo2: Foo2,
) : Foobar1(
"foobar1",
"foobar2",
), FooBar2 {
fun foo() = "foo"
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasLintViolations(
LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(3, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(5, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(6, 1, "Unexpected indentation (0) (should be 4)"),
LintViolation(7, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(8, 1, "Unexpected indentation (4) (should be 8)"),
LintViolation(9, 1, "Unexpected indentation (0) (should be 4)"),
).isFormattedAs(formattedCode)
}

@Test
fun `Issue 2115 - Given a class without an explicit constructor and with a long super type list then do not indent the class body`() {
val code =
"""
class Foo(
val bar1: Bar,
val bar2: Bar,
) : FooBar(bar1, bar2),
BarFoo1,
BarFoo2 {
// body
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasNoLintViolations()
}
}

@Test
Expand Down

0 comments on commit 1e0773f

Please sign in to comment.