Skip to content

Commit

Permalink
[Php80] Skip union callable on ClassPropertyAssignToConstructorPromot…
Browse files Browse the repository at this point in the history
…ionRector (#1101)

* Add failing test fixture for ClassPropertyAssignToConstructorPromotionRector

* Closes #1100

* cs fix

* Add PropertyAnalyzer

* [ci-review] Rector Rectify

* rectify

* clean up

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

Co-authored-by: zingimmick <zingimmick@outlook.com>
Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
3 people committed Oct 29, 2021
1 parent a7d8b39 commit 5ca93fd
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

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

final class SkipNullableCallableWithoutTypehint
{
/** @var callable|null */
public $cb;

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

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

final class SkipUnionTypedWithCallableType
{
/** @var callable|array */
public $cb;

public function __construct(callable|array $cb = null)
{
$this->cb = $cb;
}
}
22 changes: 12 additions & 10 deletions rules/Php74/Rector/Property/TypedPropertyRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\NodeAnalyzer\PropertyAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
Expand Down Expand Up @@ -71,7 +72,8 @@ public function __construct(
private VarTagRemover $varTagRemover,
private ReflectionProvider $reflectionProvider,
private PropertyFetchAnalyzer $propertyFetchAnalyzer,
private FamilyRelationsAnalyzer $familyRelationsAnalyzer
private FamilyRelationsAnalyzer $familyRelationsAnalyzer,
private PropertyAnalyzer $propertyAnalyzer
) {
}

Expand Down Expand Up @@ -246,14 +248,6 @@ private function shouldSkipNonClassLikeType(Name|NullableType|PhpParserUnionType
return false;
}

if ($typeName === 'null') {
return true;
}

if ($typeName === 'callable') {
return true;
}

if (! $this->classLikeTypeOnly) {
return false;
}
Expand Down Expand Up @@ -311,6 +305,14 @@ private function shouldSkipProperty(Property $property): bool
return true;
}

return $this->privatePropertyOnly && ! $property->isPrivate();
if (! $this->privatePropertyOnly) {
return $this->propertyAnalyzer->hasForbiddenType($property);
}

if ($property->isPrivate()) {
return $this->propertyAnalyzer->hasForbiddenType($property);
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\UnionType;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\Core\ValueObject\PhpVersionFeature;
Expand All @@ -39,7 +41,8 @@ public function __construct(
private VariableRenamer $variableRenamer,
private VarTagRemover $varTagRemover,
private ParamAnalyzer $paramAnalyzer,
private PhpDocTypeChanger $phpDocTypeChanger
private PhpDocTypeChanger $phpDocTypeChanger,
private PropertyAnalyzer $propertyAnalyzer
) {
}

Expand Down Expand Up @@ -106,6 +109,10 @@ public function refactor(Node $node): ?Node
continue;
}

if ($this->propertyAnalyzer->hasForbiddenType($property)) {
continue;
}

$this->removeNode($property);
$this->removeNode($promotionCandidate->getAssign());

Expand Down Expand Up @@ -184,6 +191,22 @@ private function shouldSkipParam(Param $param): bool
$type = $param->type;
}

return $type instanceof Identifier && $this->isName($type, 'callable');
if (! $type instanceof UnionType) {
return false;
}

foreach ($type->types as $type) {
if (! $type instanceof Identifier) {
continue;
}

if (! $this->isName($type, 'callable')) {
continue;
}

return true;
}

return false;
}
}
50 changes: 50 additions & 0 deletions src/NodeAnalyzer/PropertyAnalyzer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Rector\Core\NodeAnalyzer;

use PhpParser\Node\Stmt\Property;
use PHPStan\Type\CallableType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\NodeTypeResolver\NodeTypeResolver;

final class PropertyAnalyzer
{
public function __construct(
private NodeTypeResolver $nodeTypeResolver
) {
}

public function hasForbiddenType(Property $property): bool
{
$propertyType = $this->nodeTypeResolver->getType($property);
if ($propertyType instanceof NullType) {
return true;
}

if ($this->isCallableType($propertyType)) {
return true;
}

if (! $propertyType instanceof UnionType) {
return false;
}

$types = $propertyType->getTypes();
foreach ($types as $type) {
if ($this->isCallableType($type)) {
return true;
}
}

return false;
}

private function isCallableType(Type $type): bool
{
return $type instanceof CallableType;
}
}

0 comments on commit 5ca93fd

Please sign in to comment.