Skip to content

Commit ab46fa5

Browse files
committed
pipe
1 parent 647c058 commit ab46fa5

1 file changed

Lines changed: 48 additions & 18 deletions

File tree

rules/Php85/Rector/StmtsAwareInterface/NestedToPipeOperatorRector.php

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@
55
namespace Rector\Php85\Rector\StmtsAwareInterface;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Arg;
9+
use PhpParser\Node\Expr;
810
use PhpParser\Node\Expr\Assign;
11+
use PhpParser\Node\Expr\Cast\Array_;
12+
use PhpParser\Node\Expr\Cast\String_;
13+
use PhpParser\Node\Expr\ConstFetch;
914
use PhpParser\Node\Expr\FuncCall;
1015
use PhpParser\Node\Expr\Variable;
16+
use PhpParser\Node\Scalar\DNumber;
17+
use PhpParser\Node\Scalar\LNumber;
1118
use PhpParser\Node\Stmt;
1219
use PhpParser\Node\Stmt\Expression;
1320
use PhpParser\Node\VariadicPlaceholder;
@@ -25,7 +32,7 @@
2532
final class NestedToPipeOperatorRector extends AbstractRector implements MinPhpVersionInterface
2633
{
2734
public function getRuleDefinition(): RuleDefinition
28-
{
35+
{
2936
return new RuleDefinition(
3037
'Transform nested function calls and sequential assignments to pipe operator syntax',
3138
[
@@ -105,7 +112,7 @@ private function transformSequentialAssignments(StmtsAwareInterface $node): bool
105112

106113
/**
107114
* @param array<int, Stmt> $statements
108-
* @return array<int, Stmt>|null
115+
* @return array<int, array{stmt: Stmt, assign: Expr, funcCall: Expr\FuncCall}>|null
109116
*/
110117
private function findAssignmentChain(array $statements, int $startIndex): ?array
111118
{
@@ -122,22 +129,26 @@ private function findAssignmentChain(array $statements, int $startIndex): ?array
122129

123130
$expr = $stmt->expr;
124131
if (! $expr instanceof Assign) {
125-
break;
132+
return null;
126133
}
127134

128135
// Check if this is a simple function call with one argument
129136
if (! $expr->expr instanceof FuncCall) {
130-
break;
137+
return null;
131138
}
132139

133140
$funcCall = $expr->expr;
134141
if (count($funcCall->args) !== 1) {
135-
break;
142+
return null;
136143
}
137144

138145
$arg = $funcCall->args[0];
146+
if (! $arg instanceof Arg) {
147+
return null;
148+
}
139149

140150
if ($currentIndex === $startIndex) {
151+
141152
// First in chain - must be a variable or simple value
142153
if (! $arg->value instanceof Variable && ! $this->isSimpleValue($arg->value)) {
143154
return null;
@@ -152,9 +163,7 @@ private function findAssignmentChain(array $statements, int $startIndex): ?array
152163
$previousAssign = $chain[count($chain) - 1]['assign'];
153164
$previousVarName = $this->getName($previousAssign->var);
154165

155-
if (! $arg->value instanceof Variable || $this->getName(
156-
$arg->value
157-
) !== $previousVarName) {
166+
if (! $arg->value instanceof Variable || $this->getName($arg->value) !== $previousVarName) {
158167
break;
159168
}
160169
$chain[] = [
@@ -164,29 +173,43 @@ private function findAssignmentChain(array $statements, int $startIndex): ?array
164173
];
165174
}
166175

167-
$currentIndex += 1;
176+
++$currentIndex;
168177
}
169178

170179
return $chain;
171180
}
172181

173-
private function isSimpleValue(Node $node): bool
182+
private function isSimpleValue(Expr $expr): bool
174183
{
175-
return $node instanceof Node\Scalar\String_
176-
|| $node instanceof Node\Scalar\LNumber
177-
|| $node instanceof Node\Scalar\DNumber
178-
|| $node instanceof Node\Expr\ConstFetch
179-
|| $node instanceof Node\Expr\Array_;
184+
return $expr instanceof Variable
185+
|| $expr instanceof ConstFetch
186+
|| $expr instanceof String_
187+
|| $expr instanceof LNumber
188+
|| $expr instanceof DNumber
189+
|| $expr instanceof Array_;
180190
}
181191

192+
/**
193+
* @param array<int, array{stmt: Stmt, assign: Expr, funcCall: Expr\FuncCall}> $chain
194+
*/
182195
private function processAssignmentChain(StmtsAwareInterface $node, array $chain, int $startIndex): void
183196
{
184197
$firstAssignment = $chain[0]['assign'];
185198
$lastAssignment = $chain[count($chain) - 1]['assign'];
186199

187200
// Get the initial value from the first function call's argument
188201
$firstFuncCall = $chain[0]['funcCall'];
189-
$initialValue = $firstFuncCall->args[0]->value;
202+
203+
if (! $firstFuncCall instanceof FuncCall) {
204+
return;
205+
}
206+
207+
$firstArg = $firstFuncCall->args[0];
208+
if (! $firstArg instanceof Arg) {
209+
return;
210+
}
211+
212+
$initialValue = $firstArg->value;
190213

191214
// Build the pipe chain
192215
$pipeExpression = $initialValue;
@@ -197,6 +220,9 @@ private function processAssignmentChain(StmtsAwareInterface $node, array $chain,
197220
$pipeExpression = new Node\Expr\BinaryOp\Pipe($pipeExpression, $placeholderCall);
198221
}
199222

223+
if (! $lastAssignment instanceof Assign) {
224+
return;
225+
}
200226
// Create the final assignment
201227
$finalAssignment = new Assign($lastAssignment->var, $pipeExpression);
202228
$finalExpression = new Expression($finalAssignment);
@@ -205,7 +231,7 @@ private function processAssignmentChain(StmtsAwareInterface $node, array $chain,
205231
$endIndex = $startIndex + count($chain) - 1;
206232

207233
// Remove all intermediate statements and replace with the final pipe expression
208-
for ($i = $startIndex; $i <= $endIndex; $i++) {
234+
for ($i = $startIndex; $i <= $endIndex; ++$i) {
209235
if ($i === $startIndex) {
210236
$node->stmts[$i] = $finalExpression;
211237
} else {
@@ -240,6 +266,7 @@ private function transformNestedCalls(StmtsAwareInterface $node): bool
240266
}
241267
} elseif ($expr instanceof FuncCall) {
242268
$processedValue = $this->processNestedCalls($expr);
269+
243270
if ($processedValue !== null && $processedValue !== $expr) {
244271
$stmt->expr = $processedValue;
245272
$hasChanged = true;
@@ -250,14 +277,17 @@ private function transformNestedCalls(StmtsAwareInterface $node): bool
250277
return $hasChanged;
251278
}
252279

253-
private function processNestedCalls(Node $node): ?Node
280+
private function processNestedCalls(Node $node): ?Expr
254281
{
255282
if (! $node instanceof FuncCall) {
256283
return null;
257284
}
258285

259286
// Check if any argument is a function call
260287
foreach ($node->args as $arg) {
288+
if (! $arg instanceof Arg) {
289+
return null;
290+
}
261291
if ($arg->value instanceof FuncCall) {
262292
return $this->buildPipeExpression($node, $arg->value);
263293
}

0 commit comments

Comments
 (0)