diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRule.kt index 1a42cff94f..abd4d93c16 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRule.kt @@ -141,6 +141,7 @@ public class ChainMethodContinuationRule : chainedExpression .chainOperators .filterNot { it.isJavaClassReferenceExpression() } + .filterNot { it.isSimpleReferenceExpression() } .forEach { chainOperator -> when { chainOperator.shouldBeOnSameLineAsClosingElementOfPreviousExpressionInMethodChain() -> { @@ -160,6 +161,11 @@ public class ChainMethodContinuationRule : nextCodeSibling()?.elementType == REFERENCE_EXPRESSION && nextCodeSibling()?.firstChildLeafOrSelf()?.text == "java" + private fun ASTNode.isSimpleReferenceExpression() = + treeParent.elementType == DOT_QUALIFIED_EXPRESSION && + prevCodeSibling()?.elementType == REFERENCE_EXPRESSION && + nextCodeSibling()?.elementType == REFERENCE_EXPRESSION + private fun ChainedExpression.wrapBeforeChainOperator() = when { hasNewlineBetweenFirstAndLastChainOperator -> { diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRuleTest.kt index 5bd04417a5..0b47a17fef 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ChainMethodContinuationRuleTest.kt @@ -1011,4 +1011,31 @@ class ChainMethodContinuationRuleTest { LintViolation(6, 46, "Exceeded max line length (45)", false), ).hasNoLintViolationsExceptInAdditionalRules() } + + @Test + fun `Issue 2455 - Given a chained method including some simple reference expressions then do not wrap simple reference expressions`() { + val code = + """ + // $MAX_LINE_LENGTH_MARKER $EOL_CHAR + fun buildBar(): Foo.Bar = Foo.Bar.builder().baz().baz.build() + """.trimIndent() + val formattedCode = + """ + // $MAX_LINE_LENGTH_MARKER $EOL_CHAR + fun buildBar(): Foo.Bar = Foo.Bar + .builder() + .baz() + .baz + .build() + """.trimIndent() + chainMethodContinuationRuleAssertThat(code) + .setMaxLineLength() + .addAdditionalRuleProvider { MaxLineLengthRule() } + .hasLintViolations( + LintViolation(2, 34, "Expected newline before '.'"), + LintViolation(2, 44, "Expected newline before '.'"), + LintViolation(2, 50, "Expected newline before '.'"), + LintViolation(2, 54, "Expected newline before '.'"), + ).isFormattedAs(formattedCode) + } }