Skip to content

Commit

Permalink
Do not try to make block like syntax for expression with more than 1 …
Browse files Browse the repository at this point in the history
…lambda

Summary: Avoiding the block like syntax once more than one lambda shows up looks much better for many complicated chains.

Reviewed By: hick209

Differential Revision: D35618238

fbshipit-source-id: acb835a68439d052680fa35053545bdf2f810c2b
  • Loading branch information
strulovich authored and facebook-github-bot committed Apr 13, 2022
1 parent 1bebf0b commit 781eb2f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,9 @@ class KotlinInputAstVisitor(
*/
private fun emitQualifiedExpression(expression: KtExpression) {
val parts = breakIntoParts(expression)
val hasTrailingLambda = parts.last().isLambda()
val groupingInfos = computeGroupingInfo(parts, hasTrailingLambda)
// whether we want to make a lambda look like a block, this make Kotlin DSLs look as expected
val useBlockLikeLambdaStyle = parts.last().isLambda() && parts.count { it.isLambda() } == 1
val groupingInfos = computeGroupingInfo(parts, useBlockLikeLambdaStyle)
builder.block(expressionBreakIndent) {
val nameTag = genSym() // allows adjusting arguments indentation if a break will be made
for ((index, ktExpression) in parts.withIndex()) {
Expand All @@ -515,7 +516,7 @@ class KotlinInputAstVisitor(
builder.close()
}
// close group due to last lambda to allow block-like style in `as.forEach { ... }`
val isTrailingLambda = hasTrailingLambda && index == parts.size - 1
val isTrailingLambda = useBlockLikeLambdaStyle && index == parts.size - 1
if (isTrailingLambda) {
builder.close()
}
Expand Down Expand Up @@ -609,7 +610,7 @@ class KotlinInputAstVisitor(
*/
private fun computeGroupingInfo(
parts: List<KtExpression>,
hasTrailingLambda: Boolean
useBlockLikeLambdaStyle: Boolean
): List<GroupingInfo> {
val groupingInfos = List(parts.size) { GroupingInfo() }
var lastIndexToOpen = 0
Expand Down Expand Up @@ -639,7 +640,7 @@ class KotlinInputAstVisitor(
}
}
}
if (hasTrailingLambda) {
if (useBlockLikeLambdaStyle) {
// a trailing lambda adds a group that we stop before emitting the lambda
groupingInfos[0].groupOpenCount++
}
Expand Down
36 changes: 30 additions & 6 deletions core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -652,13 +652,16 @@ class FormatterTest {
| foo
| }
|
| // All method calls with lambdas are on one line (because they fit),
| // even though the apply() at the end requires a line break.
| // All method calls with lambdas could fit, but we avoid a block like syntax
| // and break to one call per line
| val items =
| items.map { it + 1 }.filter { it > 0 }.apply {
| //
| foo
| }
| items
| .map { it + 1 }
| .filter { it > 0 }
| .apply {
| //
| foo
| }
|
| // the lambda is indented properly with the break before it
| val items =
Expand Down Expand Up @@ -692,6 +695,27 @@ class FormatterTest {
|""".trimMargin(),
deduceMaxWidth = true)

@Test
fun `when two lambdas are in a chain, avoid block syntax`() =
assertFormatted(
"""
|class Foo : Bar() {
| fun doIt() {
| fruit.onlyBananas().forEach { banana ->
| val seeds = banana.find { it.type == SEED }
| println(seeds)
| }
|
| fruit
| .filter { isBanana(it, Bananas.types) }
| .forEach { banana ->
| val seeds = banana.find { it.type == SEED }
| println(seeds)
| }
| }
|}
|""".trimMargin())

@Test
fun `indent parameters after a break when there's a lambda afterwards`() =
assertFormatted(
Expand Down

0 comments on commit 781eb2f

Please sign in to comment.