Skip to content
Merged
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
@@ -0,0 +1,19 @@
<?php

namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Fixture;

use Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Source\SomeCacheProvider;
use Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Source\UntypedPropertyParent;

final class SkipUntypedParentProperty extends UntypedPropertyParent
{
/**
* @var SomeCacheProvider|null
*/
protected $model;

public function __construct(SomeCacheProvider $model)
{
$this->model = $model;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector\Source;

abstract class UntypedPropertyParent
{
/**
* @var SomeCacheProvider|null
*/
protected $model;
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ public function refactor(Node $node): ?Node
continue;
}

if ($this->shouldSkipUntypedParentProperty($classReflection, $propertyName)) {
continue;
}

$hasChanged = true;

// remove property from class
Expand Down Expand Up @@ -347,6 +351,25 @@ private function processUnionType(Property $property, Param $param): void
$param->type = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($paramType, TypeKind::PARAM);
}

/**
* A parent property declared without a native type cannot be typed by a child. Promotion moves the param
* type onto the property, so promoting such a property makes the class fatal:
* "Type of Child::$property must not be defined (as in class Parent)".
*/
private function shouldSkipUntypedParentProperty(ClassReflection $classReflection, string $propertyName): bool
{
foreach ($classReflection->getParents() as $parentClassReflection) {
if (! $parentClassReflection->hasNativeProperty($propertyName)) {
continue;
}

return ! $parentClassReflection->getNativeProperty($propertyName)
->hasNativeType();
}

return false;
}

private function shouldSkipParam(Param $param): bool
{
if ($param->variadic) {
Expand Down
Loading