diff --git a/src/NodeTypeResolver/Node/AttributeKey.php b/src/NodeTypeResolver/Node/AttributeKey.php index e2256a4256f..59acaf85150 100644 --- a/src/NodeTypeResolver/Node/AttributeKey.php +++ b/src/NodeTypeResolver/Node/AttributeKey.php @@ -166,4 +166,6 @@ final class AttributeKey public const string HAS_CLOSURE_WITH_VARIADIC_ARGS = 'has_closure_with_variadic_args'; public const string IS_IN_TRY_BLOCK = 'is_in_try_block'; + + public const string NEWLINE_ON_FLUENT_CALL = 'newlineOnFluentCall'; } diff --git a/src/PhpParser/Printer/BetterStandardPrinter.php b/src/PhpParser/Printer/BetterStandardPrinter.php index 442241ecd3e..9dac4166179 100644 --- a/src/PhpParser/Printer/BetterStandardPrinter.php +++ b/src/PhpParser/Printer/BetterStandardPrinter.php @@ -375,7 +375,10 @@ protected function pExpr_MethodCall(MethodCall $methodCall): string return parent::pExpr_MethodCall($methodCall); } - if (SimpleParameterProvider::provideBoolParameter(Option::NEW_LINE_ON_FLUENT_CALL) === false) { + $globalFlag = SimpleParameterProvider::provideBoolParameter(Option::NEW_LINE_ON_FLUENT_CALL); + $perNodeFlag = (bool) $methodCall->getAttribute(AttributeKey::NEWLINE_ON_FLUENT_CALL, false); + + if ($globalFlag === false && $perNodeFlag === false) { return parent::pExpr_MethodCall($methodCall); } diff --git a/tests/PhpParser/Printer/BetterStandardPrinterTest.php b/tests/PhpParser/Printer/BetterStandardPrinterTest.php index 4a75bc516a3..582ce593519 100644 --- a/tests/PhpParser/Printer/BetterStandardPrinterTest.php +++ b/tests/PhpParser/Printer/BetterStandardPrinterTest.php @@ -14,6 +14,8 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Expression; use PHPUnit\Framework\Attributes\DataProvider; +use Rector\Configuration\Option; +use Rector\Configuration\Parameter\SimpleParameterProvider; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\PhpParser\Printer\BetterStandardPrinter; use Rector\Testing\PHPUnit\AbstractLazyTestCase; @@ -80,6 +82,29 @@ public function testYield(Node $node, string $expectedPrintedNode): void $this->assertSame($expectedPrintedNode, $printedNode); } + public function testPerNodeNewlineOnFluentCallAttribute(): void + { + SimpleParameterProvider::setParameter(Option::NEW_LINE_ON_FLUENT_CALL, false); + + $innerCall = new MethodCall(new Variable('foo'), 'bar'); + $outerCall = new MethodCall($innerCall, 'baz'); + $outerCall->setAttribute(AttributeKey::NEWLINE_ON_FLUENT_CALL, true); + + $printed = $this->betterStandardPrinter->print($outerCall); + $this->assertSame('$foo->bar()' . "\n ->baz()", $printed); + } + + public function testNoNewlineOnFluentCallWithoutAttribute(): void + { + SimpleParameterProvider::setParameter(Option::NEW_LINE_ON_FLUENT_CALL, false); + + $innerCall = new MethodCall(new Variable('foo'), 'bar'); + $outerCall = new MethodCall($innerCall, 'baz'); + + $printed = $this->betterStandardPrinter->print($outerCall); + $this->assertSame('$foo->bar()->baz()', $printed); + } + /** * @return Iterator> */