Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not indent class body for classes having a long super type list #2116

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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