pinterest / ktlint

An anti-bikeshedding Kotlin linter with built-in formatter
https://pinterest.github.io/ktlint/
MIT License
6.15k stars 503 forks source link

Abstract classes after a long previous line are multilined regardless of the ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than setting #2755

Closed bdalenoord closed 4 days ago

bdalenoord commented 1 month ago

Expected Behavior

I've configured ktlint with Spotless:

    spotless {
        kotlin {
            ktlint("1.3.1")
                .editorConfigOverride(
                    mapOf(
                        "max_line_length" to "120",
                        "ktlint_standard_no-line-break-before-assignment" to "disabled",
                        "ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than" to "unset",
                        "ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than" to "unset",
                    ),
                )
        }
    }

(the spotless version is 6.25.0 and I'm using the Gradle-plugin)

As you can see, I've configured the signature_rule_force_multiline_when_parameter_count_greater_or_equal_than to unset for both class signatures as well as function signature.

I expect class signatures that don't exceed my max. line length of 120 to not be multilined.

An example:

class One(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass")
class Two(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
class Three(val one: String, val two: String)

abstract class Four(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass")
abstract class Five(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
abstract class Six(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
abstract class Seven(val one: String, val two: String)

Observed Behavior

After running spotlessKotlinApply on the class above, the output is as follows:

class One(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass")
class Two(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
class Three(val one: String, val two: String)

abstract class Four(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass")
abstract class Five(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
abstract class Six(val one: String, val two: String)

@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
abstract class Seven(
    val one: String,
    val two: String,
)

I don't understand why a previous line would cause my class Seven to be wrapped... Especially as classes Five and Six, which has the same signature, are left untouched (the one additional character for class Seven causes the behavior).

Steps to Reproduce

Create a file containing the six unformatted classes. Run spotlessKotlinApply and observe that class Six is multilined.

Your Environment

Build time: 2024-02-02 16:47:16 UTC Revision: d55c486870a0dc6f6278f53d21381396d0741c6e

Kotlin: 1.9.20 Groovy: 3.0.17 Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023 JVM: 21.0.2 (Eclipse Adoptium 21.0.2+13-LTS) OS: Linux 6.5.0-44-generic amd64


* Operating System and version: `Ubuntu 22.04`
paul-dingemans commented 1 month ago
@Suppress("UnnecessaryAbstractClass") // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
abstract class Seven(val one: String, val two: String)

It looks like that the annotation @Suppress("UnnecessaryAbstractClass") is ignored from the class signature. But the EOL comment after the annotation is not ignored. The total length of that EOL comment and the actual class signature abstract class Seven(val one: String, val two: String) together do exceed the 120 character limit.

Of course the comment on a previous line should be ignored when deciding whether the line limit is exceeded.