[TypeDeclaration] Handle default value on not inlined assignment in __construct on TypedPropertyFromStrictConstructorRector (#2008)

This commit is contained in:
Abdul Malik Ikhsan 2022-04-05 14:56:41 +07:00 committed by GitHub
parent 26d471eeaf
commit 85ff4163b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 4 deletions

View File

@ -0,0 +1,38 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Fixture;
final class ConditionallyChangedPropertyDefaultValue
{
/**
* @var string
*/
private $rootView = 'admin.index';
public function __construct()
{
if (Str::startsWith(request()->getRequestUri(), '/super-admin')) {
$this->rootView = 'super_admin.index';
}
}
}
?>
-----
<?php
namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Fixture;
final class ConditionallyChangedPropertyDefaultValue
{
private string $rootView = 'admin.index';
public function __construct()
{
if (Str::startsWith(request()->getRequestUri(), '/super-admin')) {
$this->rootView = 'super_admin.index';
}
}
}
?>

View File

@ -5,10 +5,14 @@ declare(strict_types=1);
namespace Rector\TypeDeclaration\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\NodeManipulator\PropertyManipulator;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\DeadCode\PhpDoc\TagRemover\VarTagRemover;
@ -25,7 +29,9 @@ final class TypedPropertyFromStrictConstructorRector extends AbstractRector
public function __construct(
private readonly ConstructorPropertyTypeInferer $constructorPropertyTypeInferer,
private readonly VarTagRemover $varTagRemover,
private readonly PhpDocTypeChanger $phpDocTypeChanger
private readonly PhpDocTypeChanger $phpDocTypeChanger,
private readonly PropertyFetchFinder $propertyFetchFinder,
private readonly PropertyManipulator $propertyManipulator
) {
}
@ -87,8 +93,12 @@ CODE_SAMPLE
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
$classLike = $this->betterNodeFinder->findParentType($node, Class_::class);
if (! $classLike instanceof Class_) {
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
if (! $this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::TYPED_PROPERTIES)) {
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $varType);
return $node;
@ -106,7 +116,10 @@ CODE_SAMPLE
}
$node->type = $propertyTypeNode;
$node->props[0]->default = null;
if ($this->isDefaultToBeNull($node, $classLike)) {
$node->props[0]->default = null;
}
$this->varTagRemover->removeVarTagIfUseless($phpDocInfo, $node);
@ -117,4 +130,19 @@ CODE_SAMPLE
{
return PhpVersionFeature::TYPED_PROPERTIES;
}
private function isDefaultToBeNull(Property $property, Class_ $class): bool
{
$propertyName = $this->nodeNameResolver->getName($property);
$propertyFetches = $this->propertyFetchFinder->findLocalPropertyFetchesByName($class, $propertyName);
foreach ($propertyFetches as $propertyFetch) {
$classMethod = $this->betterNodeFinder->findParentType($propertyFetch, ClassMethod::class);
if (! $this->propertyManipulator->isInlineStmtWithConstructMethod($propertyFetch, $classMethod)) {
return false;
}
}
return true;
}
}

View File

@ -226,7 +226,7 @@ final class PropertyManipulator
return null;
}
private function isInlineStmtWithConstructMethod(
public function isInlineStmtWithConstructMethod(
PropertyFetch|StaticPropertyFetch $propertyFetch,
?ClassMethod $classMethod
): bool {