Skip to content

Commit

Permalink
Fix false positive when empty parameter list is in between trailing l…
Browse files Browse the repository at this point in the history
…ambda's of a nested call expression (#2891)

Closes #2884
  • Loading branch information
paul-dingemans authored Dec 3, 2024
1 parent e098f10 commit 1bc924c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.pinterest.ktlint.ruleset.standard.rules

import com.pinterest.ktlint.rule.engine.core.api.AutocorrectDecision
import com.pinterest.ktlint.rule.engine.core.api.ElementType.CALL_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.FUNCTION_LITERAL
import com.pinterest.ktlint.rule.engine.core.api.ElementType.LAMBDA_ARGUMENT
import com.pinterest.ktlint.rule.engine.core.api.ElementType.LAMBDA_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.LPAR
import com.pinterest.ktlint.rule.engine.core.api.ElementType.RPAR
import com.pinterest.ktlint.rule.engine.core.api.ElementType.VALUE_ARGUMENT_LIST
Expand All @@ -14,6 +16,7 @@ import com.pinterest.ktlint.rule.engine.core.api.children
import com.pinterest.ktlint.rule.engine.core.api.ifAutocorrectAllowed
import com.pinterest.ktlint.rule.engine.core.api.isPartOf
import com.pinterest.ktlint.rule.engine.core.api.nextCodeSibling
import com.pinterest.ktlint.rule.engine.core.api.prevCodeSibling
import com.pinterest.ktlint.ruleset.standard.StandardRule
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

Expand All @@ -27,8 +30,9 @@ public class UnnecessaryParenthesesBeforeTrailingLambdaRule : StandardRule("unne
node: ASTNode,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> AutocorrectDecision,
) {
if (node.isPartOf(CALL_EXPRESSION) &&
node.isEmptyArgumentList() &&
if (node.isEmptyArgumentList() &&
node.isPartOf(CALL_EXPRESSION) &&
node.isNotPrecededByCallExpressionEndingWithLambdaArgument() &&
node.nextCodeSibling()?.elementType == LAMBDA_ARGUMENT
) {
emit(
Expand All @@ -46,6 +50,17 @@ public class UnnecessaryParenthesesBeforeTrailingLambdaRule : StandardRule("unne
children()
.filterNot { it.elementType == LPAR || it.elementType == RPAR }
.none()

private fun ASTNode.isNotPrecededByCallExpressionEndingWithLambdaArgument() =
prevCodeSibling()
?.takeIf { it.elementType == CALL_EXPRESSION }
?.lastChildNode
?.takeIf { it.elementType == LAMBDA_ARGUMENT }
?.lastChildNode
?.takeIf { it.elementType == LAMBDA_EXPRESSION }
?.lastChildNode
?.let { it.elementType != FUNCTION_LITERAL }
?: true
}

public val UNNECESSARY_PARENTHESES_BEFORE_TRAILING_LAMBDA_RULE_ID: RuleId = UnnecessaryParenthesesBeforeTrailingLambdaRule().ruleId
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,15 @@ class UnnecessaryParenthesesBeforeTrailingLambdaRuleTest {
.hasLintViolation(2, 24, "Empty parentheses in function call followed by lambda are unnecessary")
.isFormattedAs(formattedCode)
}

@Test
fun `Issue 2884 - Given some a call expression ending with a lambda argument, followed by an empty argument list followed by another lambda argument then do not remove empty parameter list`() {
val code =
"""
fun fooBar(foo: () -> String): (() -> String) -> String = { bar -> foo().plus(" ").plus(bar()) }
val foobar = fooBar { "Hello" }() { "world" }
""".trimIndent()
unnecessaryParenthesesBeforeTrailingLambdaRuleAssertThat(code).hasNoLintViolations()
}
}

0 comments on commit 1bc924c

Please sign in to comment.