diff --git a/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_array_dim_fetch_assign.php.inc b/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_array_dim_fetch_assign.php.inc new file mode 100644 index 00000000000..384caaa78cb --- /dev/null +++ b/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_array_dim_fetch_assign.php.inc @@ -0,0 +1,16 @@ + 'some name', + 'tplset' => null, + ]; + + public function __construct() + { + $this->default['tplset'] = 'dotty'; + } +} diff --git a/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_nested_array_dim_fetch_assign.php.inc b/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_nested_array_dim_fetch_assign.php.inc new file mode 100644 index 00000000000..ed6892938bb --- /dev/null +++ b/rules-tests/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector/Fixture/skip_nested_array_dim_fetch_assign.php.inc @@ -0,0 +1,15 @@ + ['second' => null], + ]; + + public function __construct() + { + $this->config['first']['second'] = 'value'; + } +} diff --git a/rules/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector.php b/rules/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector.php index 6dd4b633d5a..e00ac05b75e 100644 --- a/rules/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector.php +++ b/rules/DeadCode/Rector/Property/RemoveDefaultValueFromAssignedPropertyRector.php @@ -6,9 +6,12 @@ use PhpParser\Node; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\ArrayDimFetch; +use PhpParser\Node\Expr\Assign; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Return_; +use Rector\NodeAnalyzer\PropertyFetchAnalyzer; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\Rector\AbstractRector; use Rector\TypeDeclaration\AlreadyAssignDetector\ConstructorAssignDetector; @@ -23,7 +26,8 @@ final class RemoveDefaultValueFromAssignedPropertyRector extends AbstractRector { public function __construct( private readonly ConstructorAssignDetector $constructorAssignDetector, - private readonly BetterNodeFinder $betterNodeFinder + private readonly BetterNodeFinder $betterNodeFinder, + private readonly PropertyFetchAnalyzer $propertyFetchAnalyzer ) { } @@ -106,6 +110,11 @@ public function refactor(Node $node): ?Node continue; } + // partial assign, e.g. $this->items['key'] = ...; keeps the default value required + if ($this->isAssignedViaArrayDimFetch($node, $propertyName)) { + continue; + } + $propertyProperty->default = null; $hasChanged = true; } @@ -117,4 +126,25 @@ public function refactor(Node $node): ?Node return null; } + + private function isAssignedViaArrayDimFetch(Class_ $class, string $propertyName): bool + { + return $this->betterNodeFinder->findFirst($class, function (Node $subNode) use ($propertyName): bool { + if (! $subNode instanceof Assign) { + return false; + } + + $assignedExpr = $subNode->var; + if (! $assignedExpr instanceof ArrayDimFetch) { + return false; + } + + // unwrap nested dims, e.g. $this->items['first']['second'] = ... + while ($assignedExpr instanceof ArrayDimFetch) { + $assignedExpr = $assignedExpr->var; + } + + return $this->propertyFetchAnalyzer->isLocalPropertyFetchName($assignedExpr, $propertyName); + }) instanceof Assign; + } }