Kotlin / Kotlin/dataframe

Custom DataFrame KtLint ruleset for our users?

Open
#1,594 9 comments 0 reactions 1 assignee Claimed by @Jolanrensen View on GitHub
research
Dominant language
Kotlin
Stars
1.1k
Forks
83
Avg merge
4d 12h
Merged PRs (30d)
30

Description

As I learned in the talk from @paul-dingemans at Kotlin Dev Day, it's possible to create a [custom KtLint ruleset](https://pinterest.github.io/ktlint/1.8.0/api/custom-rule-set/) which would allow us to define a recommended style for using DataFrame in cases where it deviates from "ordinary" Kotlin.

There are a couple of places where this would make sense. If you look at our project, you can see we've suppressed KtLint here as well, or disabled a rule in our `.editorconfig` entirely.

There might be more, but these two seem like good candidates:

## DataFrame operation chaining
DataFrame operations often use "intermediate classes" in its DSL to form a sort-of sentence to describe what needs to be done with the data. It's okay to put these intermediate steps on separate lines if it's just a single operation being called on a dataframe:

```kt
dataFrame
.update { colA and colB }
.where { it > 10 }
.with { 100 * it }
```
However, when multiple operations need to happen after another, it's hard to tell where the instruction for one ends and the next begins:
```kt
dataFrame
.update { colA and colB }
.where { it > 10 }
.with { 100 * it }
.split { colC }
.by(",")
.into { "colC$it" }
```

In our examples and tests, we suppress `ktlint_standard_chain-method-continuation` and write it like this:

```kt
dataFrame
.update { colA and colB }.where { it > 10 }.with { 100 * it }
.split { colC }.by(",").into { "colC$it" }
```

If the contents of an invocation are too long, we could still recommend putting continuation on the same line, while requiring a full line break in between operations:

```kt
dataFrame
.update {
colA and colB
}.where {
it > 10
}.with {
100 * it
}
.split {
colC
}.by(
",",
).into {
"colC$it"
}
```
or a mix like:
```kt
dataFrame.update { colA and colB }.where { it > 10 }.with {
100 * it
}
.split { colC }.by(",").into {
"colC$it"
}
```

## `dataFrameOf(header)(values)`

Take a look at:
```kt
dataFrameOf("firstName", "lastName", "age", "city", "weight", "isHappy")(
"Alice", "Cooper", 15, "London", 54, true,
"Bob", "Dylan", 45, "Dubai", 87, true,
"Charlie", "Daniels", 20, "Moscow", null, false,
"Charlie", "Chaplin", 40, "Milan", null, true,
"Bob", "Marley", 30, "Tokyo", 68, true,
"Alice", "Wolf", 20, null, 55, false,
"Charlie", "Byrd", 30, "Moscow", 90, true,
)
```

Writing out all values like this is only possible if we suppress `ktlint:standard:argument-list-wrapping`. Otherwise, it will be formatted like:
```kt
dataFrameOf("firstName", "lastName", "age", "city", "weight", "isHappy")(
"Alice",
"Cooper",
15,
"London",
54,
true,
"Bob",
"Dylan",
45,
"Dubai",
87,
true,
...
)
```

This loses all readability of the function and makes it harder to use. Maybe we could create a custom rule for `DataFrameBuilderInvoke0` that could ignore this function or format it like this:
```kt
dataFrameOf("firstName", "lastName", "age", "city", "weight", "isHappy")(
"Alice", "Cooper", 15, "London", 54, true,
"Bob", "Dylan", 45, "Dubai", 87, true,
"Charlie", "Daniels", 20, "Moscow", null, false,
"Charlie", "Chaplin", 40, "Milan", null, true,
"Bob", "Marley", 30, "Tokyo", 68, true,
"Alice", "Wolf", 20, null, 55, false,
"Charlie", "Byrd", 30, "Moscow", 90, true,
)
```

Maybe even like this!
```kt
dataFrameOf(
"firstName", "lastName", "age", "city", "weight", "isHappy",
)(
"Alice", "Cooper", 15, "London", 54, true,
"Bob", "Dylan", 45, "Dubai", 87, true,
"Charlie", "Daniels", 20, "Moscow", null, false,
"Charlie", "Chaplin", 40, "Milan", null, true,
"Bob", "Marley", 30, "Tokyo", 68, true,
"Alice", "Wolf", 20, null, 55, false,
"Charlie", "Byrd", 30, "Moscow", 90, true,
)
```

(Yes, if we recommend people to use `dataFrameOf(vararg Pair)`, this won't be necessary anymore.)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.