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

Add rule class-signature #2119

Merged
merged 11 commits into from
Jul 21, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Added

* Add rule `class-signature`. This rule rewrites the class header to a consistent format. In code style `ktlint_official`, super types are always wrapped to a separate line. In other code styles, super types are only wrapped in classes having multiple super types. Especially for code style `ktlint_official` the class headers are rewritten in a more consistent format. See [examples in documentation](https://pinterest.github.io/ktlint/latest/rules/experimental/#class-signature). `class-signature` [#875](https://github.com/pinterest/ktlint/issues/1349), [#1349](https://github.com/pinterest/ktlint/issues/875)

### Removed

### Fixed
Expand Down
177 changes: 177 additions & 0 deletions documentation/snapshot/docs/rules/experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,183 @@ Rule id: `blank-line-before-declaration` (`standard` rule set)
!!! Note
This rule is only run when `ktlint_code_style` is set to `ktlint_official` or when the rule is enabled explicitly.

## Class signature

Rewrites the class signature to a consistent format respecting the `.editorconfig` property `max_line_length` if set. In the `ktlint_official` code style all class parameters are wrapped by default. Set `.editorconfig` property `ktlint_class_signature_wrapping_rule_always_with_minimum_parameters` to a value greater than 1 to allow class with a few parameters to be placed on a single line.
The other code styles allow an infinite amount of parameters on the same line (as long as the `max_line_length` is not exceeded) unless `.editorconfig` property `ktlint_class_signature_wrapping_rule_always_with_minimum_parameters` is set explicitly.

=== "[:material-heart:](#) Ktlint (ktlint_official)"

```kotlin
// Assume that max_line_length is not exceeded when written as single line
class Foo0
class Foo1(
a: Any
)
class Foo2(
a: Any,
b: Any
)
class Foo3(
@Foo a: Any,
b: Any,
c: Any
)
class Foo4(
a: Any,
b: Any,
c: Any
) : FooBar(a, c)
class Foo5 :
FooBar(
"bar1",
"bar2",
) {
// body
}
class Foo6(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
) {
// body
}
class Foo7(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
),
BarFoo1,
BarFoo2 {
// body
}
class Foo8
constructor(
val bar1: Bar,
val bar2: Bar,
) : FooBar(bar1, bar2),
BarFoo1,
BarFoo2 {
// body
}
```

=== "[:material-heart-off-outline:](#) Disallowed (ktlint_official)"

```kotlin
// Assume that max_line_length is not exceeded when written as single line
class Foo0()
class Foo1(a: Any)
class Foo2(a: Any, b: Any)
class Foo3(@Foo a: Any, b: Any, c: Any)
class Foo4(a: Any, b: Any, c: Any) : FooBar(a, c)
class Foo5 : FooBar(
"bar1",
"bar2",
) {
// body
}
class Foo6(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
) {
// body
}
class Foo7(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
),
BarFoo1,
BarFoo2 {
// body
}
class Foo8
constructor(
val bar1: Bar,
val bar2: Bar,
) : FooBar(bar1, bar2),
BarFoo1,
BarFoo2 {
// body
}
```

=== "[:material-heart:](#) Ktlint (non ktlint_official)"

```kotlin
// Assume that the last allowed character is
// at the X character on the right X
class Foo0
class Foo1(
a: Any
)
class Foo2(a: Any)
class Foo3(
a: Any,
b: Any
)
class Foo4(a: Any, b: Any)
class Foo5(@Foo a: Any, b: Any, c: Any)
class Foo6(a: Any, b: Any, c: Any) :
FooBar(a, c)
class Foo7 : FooBar(
"bar1",
"bar2",
) {
// body
}
class Foo8(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
) {
// body
}
class Foo9(
val bar1: Bar,
val bar2: Bar
) : FooBar(
bar1,
bar2
),
BarFoo1,
BarFoo2 {
// body
}
class Foo10
constructor(
val bar1: Bar,
val bar2: Bar,
) : FooBar(bar1, bar2),
BarFoo1,
BarFoo2 {
// body
}
```

=== "[:material-heart-off-outline:](#) Disallowed (non ktlint_official)"

```kotlin
// Assume that the last allowed character is
// at the X character on the right X
class Foo0()
class Foo6(a: Any, b: Any, c: Any) : FooBar(a, c)
```

Rule id: `class-signature` (`standard` rule set)

## Discouraged comment location

Detect discouraged comment locations (no autocorrect).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import com.pinterest.ktlint.rule.engine.core.api.Rule
import com.pinterest.ktlint.rule.engine.core.api.RuleId
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

public class NoVarRule : Rule(
ruleId = RuleId("$CUSTOM_RULE_SET_ID:no-var"),
about = About(),
) {
public class NoVarRule :
Rule(
ruleId = RuleId("$CUSTOM_RULE_SET_ID:no-var"),
about = About(),
) {
override fun beforeVisitChildNodes(
node: ASTNode,
autoCorrect: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import kotlin.io.path.relativeToOrSelf

private val LOGGER = KotlinLogging.logger {}.initKtLintKLogger()

class ApiTestRunner(private val tempDir: Path) {
class ApiTestRunner(
private val tempDir: Path,
) {
fun prepareTestProject(testProjectName: String): Path {
val testProjectPath = TEST_PROJECTS_PATHS.resolve(testProjectName)
assert(Files.exists(testProjectPath)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ public class Baseline(
*/
public fun loadBaseline(path: String): Baseline = BaselineLoader(path).load()

private class BaselineLoader(private val path: String) {
private class BaselineLoader(
private val path: String,
) {
var ruleReferenceWithoutRuleSetIdPrefix = 0

fun load(): Baseline {
Expand Down Expand Up @@ -165,7 +167,8 @@ private class BaselineLoader(private val path: String) {
}
}
},
detail = "", // Not available in the baseline
// Detail is not available in the baseline
detail = "",
status = BASELINE_IGNORED,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import com.pinterest.ktlint.cli.reporter.core.api.ReporterV2
import java.io.PrintStream
import java.util.concurrent.ConcurrentHashMap

public class BaselineReporter(private val out: PrintStream) : ReporterV2 {
public class BaselineReporter(
private val out: PrintStream,
) : ReporterV2 {
private val acc = ConcurrentHashMap<String, MutableList<KtlintCliError>>()

override fun onLintError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import java.io.PrintStream
import java.util.ArrayList
import java.util.concurrent.ConcurrentHashMap

public class CheckStyleReporter(private val out: PrintStream) : ReporterV2 {
public class CheckStyleReporter(
private val out: PrintStream,
) : ReporterV2 {
private val acc = ConcurrentHashMap<String, MutableList<KtlintCliError>>()

override fun onLintError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.pinterest.ktlint.cli.reporter.format
/**
* Stripped down version of https://github.com/ziggy42/kolor (ziggy42/kolor#6).
*/
public enum class Color(public val code: Int) {
public enum class Color(
public val code: Int,
) {
BLACK(30),
RED(31),
GREEN(32),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import com.pinterest.ktlint.cli.reporter.core.api.ReporterV2
import java.io.PrintStream
import java.util.concurrent.ConcurrentHashMap

public class HtmlReporter(private val out: PrintStream) : ReporterV2 {
public class HtmlReporter(
private val out: PrintStream,
) : ReporterV2 {
private val acc = ConcurrentHashMap<String, MutableList<KtlintCliError>>()
private var issueCount = 0
private var correctedCount = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import java.io.PrintStream
import java.util.ArrayList
import java.util.concurrent.ConcurrentHashMap

public class JsonReporter(private val out: PrintStream) : ReporterV2 {
public class JsonReporter(
private val out: PrintStream,
) : ReporterV2 {
private val acc = ConcurrentHashMap<String, MutableList<KtlintCliError>>()

override fun onLintError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.pinterest.ktlint.cli.reporter.plain
/**
* Stripped down version of https://github.com/ziggy42/kolor (ziggy42/kolor#6).
*/
public enum class Color(public val code: Int) {
public enum class Color(
public val code: Int,
) {
BLACK(30),
RED(31),
GREEN(32),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ internal fun String.sanitize(): String =
if (it.endsWith('/')) it else "$it/"
}

public class SarifReporter(private val out: PrintStream) : ReporterV2 {
public class SarifReporter(
private val out: PrintStream,
) : ReporterV2 {
private val results: MutableList<Result> = mutableListOf()
private var workingDirectory: File? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import java.io.Serializable
* `META-INF/services/com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3` (see `ktlint-ruleset-standard/src/main/resources`
* for an example).
*/
public abstract class RuleSetProviderV3(public val id: RuleSetId) : Serializable {
public abstract class RuleSetProviderV3(
public val id: RuleSetId,
) : Serializable {
/**
* Gets a group of related [RuleProvider]s. A provided rule is not guaranteed to be run as rules can be disabled,
* for example via ".editorconfig" properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ internal class ReporterAggregator(
val output: String?,
)

private class AggregatedReporter(val reporters: List<ReporterV2>) : ReporterV2 {
private class AggregatedReporter(
val reporters: List<ReporterV2>,
) : ReporterV2 {
override fun beforeAll() = reporters.forEach(ReporterV2::beforeAll)

override fun before(file: String) = reporters.forEach { it.before(file) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import kotlin.io.path.relativeToOrSelf

private val LOGGER = KotlinLogging.logger {}.initKtLintKLogger()

class CommandLineTestRunner(private val tempDir: Path) {
class CommandLineTestRunner(
private val tempDir: Path,
) {
private val ktlintCli: String = System.getProperty("ktlint-cli")

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ internal class OsEnvironment private constructor(
}

private class CaseInsensitiveMap<V : Any> :
TreeMap<String, V>(java.lang.String.CASE_INSENSITIVE_ORDER), MutableMap<String, V>
TreeMap<String, V>(java.lang.String.CASE_INSENSITIVE_ORDER),
MutableMap<String, V>
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ internal class FileUtilsTest {
patterns =
listOf(
pattern,
"/some/non/existing/file", // This prevents the default patterns to be added
// Prevents the default patterns to be added by specifying a file
"/some/non/existing/file",
),
rootDir = ktlintTestFileSystem.resolve("project1"),
)
Expand Down Expand Up @@ -386,7 +387,8 @@ internal class FileUtilsTest {
patterns =
listOf(
pattern,
"/some/non/existing/file", // This prevents the default patterns to be added
// Prevents the default patterns to be added by specifying a file
"/some/non/existing/file",
),
rootDir = ktlintTestFileSystem.resolve("project1"),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfigProper
import com.pinterest.ktlint.rule.engine.core.internal.IdNamingPolicy
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

public data class RuleId(public val value: String) {
public data class RuleId(
public val value: String,
) {
init {
IdNamingPolicy.enforceRuleIdNaming(value)
}
Expand All @@ -26,7 +28,9 @@ public data class RuleId(public val value: String) {
}
}

public data class RuleSetId(public val value: String) {
public data class RuleSetId(
public val value: String,
) {
init {
IdNamingPolicy.enforceRuleSetIdNaming(value)
}
Expand Down
Loading