Skip to content

Commit

Permalink
[Php74] Do not remove array of type[] doc type on TypedPropertyRector…
Browse files Browse the repository at this point in the history
… when php 8.0 feature enabled (#1811)

* [Php74] Do not remove array of string doc type on TypedPropertyRector when php 8.0 feature enabled

* update fixture

* update fixture

* Fixed 🎉

* [ci-review] Rector Rectify

* remove array of mixed in doc in multiple with null

* fixed 🎉

* clean up

* clean up

* clean up

* clean up

* final touch: move check to PhpDocTypeChanger to collect allowed types

* phpstan

* final touch: clean up

* final touch: clean up

* final touch: clean up, make recurisve

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Feb 13, 2022
1 parent d3d562d commit 9077ef4
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Constant\ConstantArrayType;
Expand All @@ -19,6 +20,7 @@
use Rector\BetterPhpDocParser\Comment\CommentsMerger;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode;
use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode;
use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareCallableTypeNode;
use Rector\NodeNameResolver\NodeNameResolver;
Expand All @@ -37,6 +39,7 @@ final class PhpDocTypeChanger
GenericTypeNode::class,
SpacingAwareArrayTypeNode::class,
SpacingAwareCallableTypeNode::class,
ArrayShapeNode::class,
];

public function __construct(
Expand Down Expand Up @@ -150,6 +153,19 @@ public function changeParamType(PhpDocInfo $phpDocInfo, Type $newType, Param $pa
}
}

public function isAllowed(TypeNode $typeNode): bool
{
if ($typeNode instanceof BracketsAwareUnionTypeNode) {
foreach ($typeNode->types as $type) {
if ($this->isAllowed($type)) {
return true;
}
}
}

return in_array($typeNode::class, self::ALLOWED_TYPES, true);
}

public function copyPropertyDocToParam(Property $property, Param $param): void
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
Expand All @@ -167,24 +183,24 @@ public function copyPropertyDocToParam(Property $property, Param $param): void
return;
}

$phpDocInfo->removeByType(VarTagValueNode::class);
$param->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);

$functionLike = $param->getAttribute(AttributeKey::PARENT_NODE);
$paramVarName = $this->nodeNameResolver->getName($param->var);

if (! $functionLike instanceof ClassMethod) {
return;
}

if (! in_array($varTag->type::class, self::ALLOWED_TYPES, true)) {
if (! $this->isAllowed($varTag->type)) {
return;
}

if (! is_string($paramVarName)) {
return;
}

$phpDocInfo->removeByType(VarTagValueNode::class);
$param->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);

$phpDocInfo = $functionLike->getAttribute(AttributeKey::PHP_DOC_INFO);
$paramType = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($varTag, $property);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\Fixture;

final class DefaultValuesForNullableArray
{
/**
* @var mixed[]|null
*/
private ?array $rooms = null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class DoNotRemoveArrayOfStringTypeDoc
{
/**
* @var string|string[]|null
*/
private $property;
}

?>
-----
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class DoNotRemoveArrayOfStringTypeDoc
{
/**
* @var string|string[]|null
*/
private array|string|null $property = null;
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class RemoveArrayNoType
{
/**
* @var string|array|null
*/
private $property;
}

?>
-----
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class RemoveArrayNoType
{
private array|string|null $property = null;
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class DoNotRemoveArrayOfMixedTypeDocInMultipleWithNull
{
/**
* @var string|mixed[]|null
*/
private $property;
}

?>
-----
<?php

namespace Rector\Tests\Php74\Rector\Property\TypedPropertyRector\FixtureUnionIntersectionTypes;

final class DoNotRemoveArrayOfMixedTypeDocInMultipleWithNull
{
/**
* @var string|mixed[]|null
*/
private array|string|null $property = null;
}

?>
70 changes: 4 additions & 66 deletions rules/DeadCode/PhpDoc/TagRemover/VarTagRemover.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,25 @@

namespace Rector\DeadCode\PhpDoc\TagRemover;

use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Generic\TemplateObjectWithoutClassType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode;
use Rector\BetterPhpDocParser\ValueObject\Type\SpacingAwareArrayTypeNode;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\DeadCode\PhpDoc\DeadVarTagValueNodeAnalyzer;
use Rector\PHPStanStaticTypeMapper\DoctrineTypeAnalyzer;
use Rector\StaticTypeMapper\StaticTypeMapper;

final class VarTagRemover
{
public function __construct(
private readonly DoctrineTypeAnalyzer $doctrineTypeAnalyzer,
private readonly StaticTypeMapper $staticTypeMapper,
private readonly PhpDocInfoFactory $phpDocInfoFactory,
private readonly DeadVarTagValueNodeAnalyzer $deadVarTagValueNodeAnalyzer
private readonly DeadVarTagValueNodeAnalyzer $deadVarTagValueNodeAnalyzer,
private readonly PhpDocTypeChanger $phpDocTypeChanger
) {
}

Expand Down Expand Up @@ -71,66 +64,11 @@ public function removeVarPhpTagValueNodeIfNotComment(Expression | Property | Par
return;
}

// keep generic types
if ($varTagValueNode->type instanceof GenericTypeNode) {
return;
}

// keep string[] etc.
if ($this->isNonBasicArrayType($node, $varTagValueNode)) {
if ($this->phpDocTypeChanger->isAllowed($varTagValueNode->type)) {
return;
}

$phpDocInfo->removeByType(VarTagValueNode::class);
}

private function isNonBasicArrayType(Expression | Param | Property $node, VarTagValueNode $varTagValueNode): bool
{
if ($varTagValueNode->type instanceof BracketsAwareUnionTypeNode) {
foreach ($varTagValueNode->type->types as $type) {
if ($type instanceof SpacingAwareArrayTypeNode && $this->isArrayOfClass($node, $type)) {
return true;
}

// keep generic types
if ($type instanceof GenericTypeNode) {
return true;
}
}
}

if (! $this->isArrayTypeNode($varTagValueNode)) {
return false;
}

return (string) $varTagValueNode->type !== 'array';
}

private function isArrayTypeNode(VarTagValueNode $varTagValueNode): bool
{
return in_array(
$varTagValueNode->type::class,
[SpacingAwareArrayTypeNode::class, ArrayShapeNode::class],
true
);
}

private function isArrayOfClass(Node $node, SpacingAwareArrayTypeNode $spacingAwareArrayTypeNode): bool
{
if ($spacingAwareArrayTypeNode->type instanceof SpacingAwareArrayTypeNode) {
return $this->isArrayOfClass($node, $spacingAwareArrayTypeNode->type);
}

$staticType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
$spacingAwareArrayTypeNode,
$node
);

if (! $staticType instanceof ArrayType) {
return false;
}

$itemType = $staticType->getItemType();
return $itemType instanceof ObjectType;
}
}

0 comments on commit 9077ef4

Please sign in to comment.