diff --git a/config/config.php b/config/config.php index 6d09ce58b2d..c4d4780451e 100644 --- a/config/config.php +++ b/config/config.php @@ -31,4 +31,6 @@ return static function (RectorConfig $rectorConfig) : void { foreach ($extensionConfigResolver->provide() as $extensionConfigFile) { $rectorConfig->import($extensionConfigFile); } + // use original php-parser printer to avoid BC break on fluent call + $rectorConfig->newLineOnFluentCall(\false); }; diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index a8a3c7e4d1b..5ce8a0b84ee 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '3122ef482389945d97c26bb3ff5c2b0b3faf867b'; + public const PACKAGE_VERSION = '08d73a1af5ebc77bf37e9854fc1aca76cd5fcbcb'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-03-28 09:09:29'; + public const RELEASE_DATE = '2024-03-28 17:03:10'; /** * @var int */ diff --git a/src/Config/RectorConfig.php b/src/Config/RectorConfig.php index 092538d7cdb..e383959d437 100644 --- a/src/Config/RectorConfig.php +++ b/src/Config/RectorConfig.php @@ -247,6 +247,10 @@ final class RectorConfig extends Container { SimpleParameterProvider::setParameter(Option::SYMFONY_CONTAINER_PHP_PATH_PARAMETER, $filePath); } + public function newLineOnFluentCall(bool $enabled = \true) : void + { + SimpleParameterProvider::setParameter(Option::NEW_LINE_ON_FLUENT_CALL, $enabled); + } /** * @param string[] $extensions */ diff --git a/src/Configuration/Option.php b/src/Configuration/Option.php index dc537fb3ba6..cd7197cbf54 100644 --- a/src/Configuration/Option.php +++ b/src/Configuration/Option.php @@ -71,6 +71,11 @@ final class Option * @var string */ public const SYMFONY_CONTAINER_PHP_PATH_PARAMETER = 'symfony_container_php_path'; + /** + * @internal Use @see \Rector\Config\RectorConfig::newLineOnFluentCall() + * @var string + */ + public const NEW_LINE_ON_FLUENT_CALL = 'new_line_on_fluent_call'; /** * @var string */ diff --git a/src/Configuration/RectorConfigBuilder.php b/src/Configuration/RectorConfigBuilder.php index 0b4e3a089e9..de60091b4b9 100644 --- a/src/Configuration/RectorConfigBuilder.php +++ b/src/Configuration/RectorConfigBuilder.php @@ -140,13 +140,17 @@ final class RectorConfigBuilder /** * To make sure type declarations set and level are not duplicated, * as both contain same rules - * @var bool + * @var bool|null */ - private $isTypeCoverageLevelUsed = \false; + private $isTypeCoverageLevelUsed; /** - * @var bool + * @var bool|null */ - private $isDeadCodeLevelUsed = \false; + private $isDeadCodeLevelUsed; + /** + * @var bool|null + */ + private $isFluentNewLine; /** * @var RegisteredService[] */ @@ -154,10 +158,10 @@ final class RectorConfigBuilder public function __invoke(RectorConfig $rectorConfig) : void { $uniqueSets = \array_unique($this->sets); - if (\in_array(SetList::TYPE_DECLARATION, $uniqueSets, \true) && $this->isTypeCoverageLevelUsed) { + if (\in_array(SetList::TYPE_DECLARATION, $uniqueSets, \true) && $this->isTypeCoverageLevelUsed === \true) { throw new InvalidConfigurationException(\sprintf('Your config already enables type declarations set.%sRemove "->withTypeCoverageLevel()" as it only duplicates it, or remove type declaration set.', \PHP_EOL)); } - if (\in_array(SetList::DEAD_CODE, $uniqueSets, \true) && $this->isDeadCodeLevelUsed) { + if (\in_array(SetList::DEAD_CODE, $uniqueSets, \true) && $this->isDeadCodeLevelUsed === \true) { throw new InvalidConfigurationException(\sprintf('Your config already enables dead code set.%sRemove "->withDeadCodeLevel()" as it only duplicates it, or remove dead code set.', \PHP_EOL)); } if ($uniqueSets !== []) { @@ -240,6 +244,9 @@ final class RectorConfigBuilder if ($this->symfonyContainerPhpFile !== null) { $rectorConfig->symfonyContainerPhp($this->symfonyContainerPhpFile); } + if ($this->isFluentNewLine !== null) { + $rectorConfig->newLineOnFluentCall($this->isFluentNewLine); + } } /** * @param string[] $paths @@ -541,6 +548,11 @@ final class RectorConfigBuilder $this->rules = \array_merge($this->rules, $levelRules); return $this; } + public function withFluentCallNewLine(bool $isFluentNewLine = \true) : self + { + $this->isFluentNewLine = $isFluentNewLine; + return $this; + } public function registerService(string $className, ?string $alias = null, ?string $tag = null) : self { $this->registerServices[] = new RegisteredService($className, $alias, $tag); diff --git a/src/PhpParser/Printer/BetterStandardPrinter.php b/src/PhpParser/Printer/BetterStandardPrinter.php index 5a3811f3d92..40ee379223d 100644 --- a/src/PhpParser/Printer/BetterStandardPrinter.php +++ b/src/PhpParser/Printer/BetterStandardPrinter.php @@ -6,11 +6,14 @@ namespace Rector\PhpParser\Printer; use RectorPrefix202403\Nette\Utils\Strings; use PhpParser\Comment; use PhpParser\Node; +use PhpParser\Node\Arg; use PhpParser\Node\AttributeGroup; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrowFunction; +use PhpParser\Node\Expr\CallLike; use PhpParser\Node\Expr\Closure; +use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Expr\Yield_; use PhpParser\Node\Param; @@ -134,8 +137,7 @@ final class BetterStandardPrinter extends Standard if ($comments === []) { return parent::pExpr_ArrowFunction($arrowFunction); } - $indentSize = SimpleParameterProvider::provideIntParameter(Option::INDENT_SIZE); - $indent = \str_repeat($this->getIndentCharacter(), $this->indentLevel) . \str_repeat($this->getIndentCharacter(), $indentSize); + $indent = $this->resolveIndentSpaces(); $text = "\n" . $indent; foreach ($comments as $key => $comment) { $commentText = $key > 0 ? $indent . $comment->getText() : $comment->getText(); @@ -355,6 +357,27 @@ final class BetterStandardPrinter extends Standard } return parent::pScalar_LNumber($lNumber); } + private function resolveIndentSpaces() : string + { + $indentSize = SimpleParameterProvider::provideIntParameter(Option::INDENT_SIZE); + return \str_repeat($this->getIndentCharacter(), $this->indentLevel) . \str_repeat($this->getIndentCharacter(), $indentSize); + } + protected function pExpr_MethodCall(MethodCall $methodCall) : string + { + if (SimpleParameterProvider::provideBoolParameter(Option::NEW_LINE_ON_FLUENT_CALL) === \false) { + return parent::pExpr_MethodCall($methodCall); + } + if ($methodCall->var instanceof CallLike) { + foreach ($methodCall->args as $arg) { + if (!$arg instanceof Arg) { + continue; + } + $arg->value->setAttribute(AttributeKey::ORIGINAL_NODE, null); + } + return $this->pDereferenceLhs($methodCall->var) . "\n" . $this->resolveIndentSpaces() . "->" . $this->pObjectProperty($methodCall->name) . '(' . $this->pMaybeMultiline($methodCall->args) . ')'; + } + return parent::pExpr_MethodCall($methodCall); + } /** * Keep attributes on newlines */ diff --git a/src/Testing/PHPUnit/AbstractRectorTestCase.php b/src/Testing/PHPUnit/AbstractRectorTestCase.php index 0551b863375..9bf22a8a2c4 100644 --- a/src/Testing/PHPUnit/AbstractRectorTestCase.php +++ b/src/Testing/PHPUnit/AbstractRectorTestCase.php @@ -60,6 +60,7 @@ abstract class AbstractRectorTestCase extends \Rector\Testing\PHPUnit\AbstractLa SimpleParameterProvider::setParameter(Option::INDENT_CHAR, ' '); SimpleParameterProvider::setParameter(Option::INDENT_SIZE, 4); SimpleParameterProvider::setParameter(Option::POLYFILL_PACKAGES, []); + SimpleParameterProvider::setParameter(Option::NEW_LINE_ON_FLUENT_CALL, \false); } protected function setUp() : void {