diff --git a/phpstan.neon b/phpstan.neon index d5b1a3404f6..98f6c4fccf8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -222,7 +222,7 @@ parameters: - '#Register "Rector\\Php80\\Rector\\NotIdentical\\MbStrContainsRector" service to "php80\.php" config set#' - - '#Register "Rector\\Php85\\Rector\\StmtsAwareInterface\\NestedToPipeOperatorRector" service to "php85\.php" config set#' + - '#Register "Rector\\Php85\\Rector\\StmtsAwareInterface\\SequentialAssignmentsToPipeOperatorRector" service to "php85\.php" config set#' # closure detailed - '#Method Rector\\Config\\RectorConfig\:\:singleton\(\) has parameter \$concrete with no signature specified for Closure#' diff --git a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/nested_func.php.inc b/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/nested_func.php.inc deleted file mode 100644 index 0dabf1c3548..00000000000 --- a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/nested_func.php.inc +++ /dev/null @@ -1,16 +0,0 @@ - ------ - trim(...); - -?> diff --git a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/skip_single_call.php.inc b/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/skip_single_call.php.inc deleted file mode 100644 index 575964d5b07..00000000000 --- a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/skip_single_call.php.inc +++ /dev/null @@ -1,6 +0,0 @@ -rule(NestedToPipeOperatorRector::class); -}; diff --git a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/basic.php.inc b/rules-tests/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector/Fixture/basic.php.inc similarity index 54% rename from rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/basic.php.inc rename to rules-tests/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector/Fixture/basic.php.inc index 35a5992d32e..4b03f35742b 100644 --- a/rules-tests/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector/Fixture/basic.php.inc +++ b/rules-tests/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector/Fixture/basic.php.inc @@ -1,6 +1,6 @@ rule(SequentialAssignmentsToPipeOperatorRector::class); +}; diff --git a/rules/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector.php b/rules/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector.php similarity index 69% rename from rules/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector.php rename to rules/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector.php index 32421f60b13..2fcb3454293 100644 --- a/rules/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector.php +++ b/rules/Php85/Rector/StmtsAwareInterface/SequentialAssignmentsToPipeOperatorRector.php @@ -24,9 +24,9 @@ /** * @see https://wiki.php.net/rfc/pipe-operator-v3 - * @see \Rector\Tests\Php85\Rector\StmtsAwareInterface\NestedToPipeOperatorRector\NestedToPipeOperatorRectorTest + * @see \Rector\Tests\Php85\Rector\StmtsAwareInterface\SequentialAssignmentsToPipeOperatorRector\SequentialAssignmentsToPipeOperatorRectorTest */ -final class NestedToPipeOperatorRector extends AbstractRector implements MinPhpVersionInterface +final class SequentialAssignmentsToPipeOperatorRector extends AbstractRector implements MinPhpVersionInterface { public function __construct( private readonly ExprAnalyzer $exprAnalyzer @@ -36,23 +36,24 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( - 'Transform nested function calls and sequential assignments to pipe operator syntax', + 'Transform sequential assignments to pipe operator syntax', [ new CodeSample( <<<'CODE_SAMPLE' $value = "hello world"; -$result1 = function3($value); +$result1 = function1($value); $result2 = function2($result1); -$result = function1($result2); + +$result = function3($result2); CODE_SAMPLE , <<<'CODE_SAMPLE' $value = "hello world"; $result = $value - |> function3(...) + |> function1(...) |> function2(...) - |> function1(...); + |> function3(...); CODE_SAMPLE ), ] @@ -80,40 +81,25 @@ public function refactor(Node $node): ?Node $hasChanged = false; - // First, try to transform sequential assignments - $sequentialChanged = $this->transformSequentialAssignments($node); - if ($sequentialChanged) { - $hasChanged = true; - } - - // Then, transform nested function calls - $nestedChanged = $this->transformNestedCalls($node); - if ($nestedChanged) { - $hasChanged = true; - } - - return $hasChanged ? $node : null; - } - - private function transformSequentialAssignments(StmtsAwareInterface $stmtsAware): bool - { - $hasChanged = false; - - $statements = $stmtsAware->stmts; + $statements = $node->stmts; $totalStatements = count($statements) - 1; for ($i = 0; $i < $totalStatements; ++$i) { $chain = $this->findAssignmentChain($statements, $i); if ($chain && count($chain) >= 2) { - $this->processAssignmentChain($stmtsAware, $chain, $i); + $this->processAssignmentChain($node, $chain, $i); $hasChanged = true; // Skip processed statements $i += count($chain) - 1; } } - return $hasChanged; + if (! $hasChanged) { + return null; + } + + return $node; } /** @@ -243,63 +229,6 @@ private function processAssignmentChain(StmtsAwareInterface $stmtsAware, array $ $stmtsAware->stmts = $stmts; } - private function transformNestedCalls(StmtsAwareInterface $stmtsAware): bool - { - $hasChanged = false; - - foreach ($stmtsAware->stmts as $stmt) { - if (! $stmt instanceof Expression) { - continue; - } - - $expr = $stmt->expr; - - if ($expr instanceof Assign) { - $assignedValue = $expr->expr; - $processedValue = $this->processNestedCalls($assignedValue); - - if ($processedValue instanceof Expr && $processedValue !== $assignedValue) { - $expr->expr = $processedValue; - $hasChanged = true; - } - } elseif ($expr instanceof FuncCall) { - $processedValue = $this->processNestedCalls($expr); - - if ($processedValue instanceof Expr && $processedValue !== $expr) { - $stmt->expr = $processedValue; - $hasChanged = true; - } - } - } - - return $hasChanged; - } - - private function processNestedCalls(Node $node): ?Expr - { - if (! $node instanceof FuncCall) { - return null; - } - - // Check if any argument is a function call - foreach ($node->args as $arg) { - if (! $arg instanceof Arg) { - return null; - } - - if ($arg->value instanceof FuncCall) { - return $this->buildPipeExpression($node, $arg->value); - } - } - - return null; - } - - private function buildPipeExpression(FuncCall $outerCall, FuncCall $innerCall): Pipe - { - return new Pipe($innerCall, $this->createPlaceholderCall($outerCall)); - } - private function createPlaceholderCall(FuncCall $funcCall): FuncCall { return new FuncCall($funcCall->name, [new VariadicPlaceholder()]);