Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use stdClass;

class ArrayUnionGenericSameType
{
protected array $dependencies = [
private array $dependencies = [
stdClass::class,
DateTime::class,
];
Expand All @@ -27,7 +27,7 @@ class ArrayUnionGenericSameType
/**
* @var array<int, class-string<\stdClass>|class-string<\DateTime>>
*/
protected array $dependencies = [
private array $dependencies = [
stdClass::class,
DateTime::class,
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromPropertyDefaultsRector\Fixture;

final class SkipEmptyNestedArray
{
private array $payload = ['create' => [], 'update' => []];

public function add(string $key, array $item): void
{
$this->payload['create'][$key] = $item;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rector\Tests\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromPropertyDefaultsRector\Fixture;

class SkipNonPrivateProperty
{
protected array $configParams = ['enabled' => true, 'name' => 'value'];
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\ArrayItem;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Identifier;
use PhpParser\Node\PropertyItem;
Expand Down Expand Up @@ -80,6 +81,11 @@ public function refactor(Node $node): ?Node
continue;
}

// only private properties are safe; a protected/public one can be reassigned with a wider type by a child class we cannot see here
if (! $property->isPrivate()) {
continue;
}

if (count($property->props) > 1) {
continue;
}
Expand All @@ -89,6 +95,11 @@ public function refactor(Node $node): ?Node
continue;
}

// an empty nested array default generalizes to never[], which then rejects every real value assigned later
if ($this->hasEmptyNestedArray($soleProperty->default)) {
continue;
}

$propertyDefaultType = $this->getType($soleProperty->default);

$propertyPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
Expand Down Expand Up @@ -118,6 +129,29 @@ public function refactor(Node $node): ?Node
return $node;
}

private function hasEmptyNestedArray(Array_ $array): bool
{
foreach ($array->items as $arrayItem) {
if (! $arrayItem instanceof ArrayItem) {
continue;
}

if (! $arrayItem->value instanceof Array_) {
continue;
}

if ($arrayItem->value->items === []) {
return true;
}

if ($this->hasEmptyNestedArray($arrayItem->value)) {
return true;
}
}

return false;
}

private function hasUsefulParentPropertyVarTag(Class_ $class, Property $property, Type $propertyDefaultType): bool
{
$propertyName = $this->getName($property);
Expand Down
Loading