Skip to content

Commit

Permalink
[DeadCode] Add Function_ support on RemoveUselessReturnTagRector (#5325)
Browse files Browse the repository at this point in the history
  • Loading branch information
samsonasik committed Dec 5, 2023
1 parent 005ccc3 commit 4531aeb
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
@@ -0,0 +1,28 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;

use stdClass;

/**
* @return stdClass
*/
function foo(): stdClass
{
return new stdClass();
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;

use stdClass;

function foo(): stdClass
{
return new stdClass();
}

?>
15 changes: 8 additions & 7 deletions rules/DeadCode/PhpDoc/DeadReturnTagValueNodeAnalyzer.php
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Analyser\Scope;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
Expand Down Expand Up @@ -34,9 +35,9 @@ public function __construct(
) {
}

public function isDead(ReturnTagValueNode $returnTagValueNode, ClassMethod $classMethod): bool
public function isDead(ReturnTagValueNode $returnTagValueNode, ClassMethod|Function_ $functionLike): bool
{
$returnType = $classMethod->getReturnType();
$returnType = $functionLike->getReturnType();
if ($returnType === null) {
return false;
}
Expand All @@ -45,7 +46,7 @@ public function isDead(ReturnTagValueNode $returnTagValueNode, ClassMethod $clas
return false;
}

$scope = $classMethod->getAttribute(AttributeKey::SCOPE);
$scope = $functionLike->getAttribute(AttributeKey::SCOPE);
if ($scope instanceof Scope && $scope->isInTrait() && $returnTagValueNode->type instanceof ThisTypeNode) {
return false;
}
Expand All @@ -57,9 +58,9 @@ public function isDead(ReturnTagValueNode $returnTagValueNode, ClassMethod $clas
if (! $this->typeComparator->arePhpParserAndPhpStanPhpDocTypesEqual(
$returnType,
$returnTagValueNode->type,
$classMethod,
$functionLike,
)) {
return $this->isDeadNotEqual($returnTagValueNode, $returnType, $classMethod);
return $this->isDeadNotEqual($returnTagValueNode, $returnType, $functionLike);
}

if ($this->phpDocTypeChanger->isAllowed($returnTagValueNode->type)) {
Expand Down Expand Up @@ -91,7 +92,7 @@ private function isNeverReturnType(Node $node): bool
return $node instanceof Identifier && $node->toString() === 'never';
}

private function isDeadNotEqual(ReturnTagValueNode $returnTagValueNode, Node $node, ClassMethod $classMethod): bool
private function isDeadNotEqual(ReturnTagValueNode $returnTagValueNode, Node $node, ClassMethod|Function_ $functionLike): bool
{
if ($returnTagValueNode->type instanceof IdentifierTypeNode && (string) $returnTagValueNode->type === 'void') {
return true;
Expand All @@ -100,7 +101,7 @@ private function isDeadNotEqual(ReturnTagValueNode $returnTagValueNode, Node $no
$nodeType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($node);
$docType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
$returnTagValueNode->type,
$classMethod
$functionLike
);

return $docType instanceof UnionType && $this->typeComparator->areTypesEqual(
Expand Down
5 changes: 3 additions & 2 deletions rules/DeadCode/PhpDoc/TagRemover/ReturnTagRemover.php
Expand Up @@ -5,6 +5,7 @@
namespace Rector\DeadCode\PhpDoc\TagRemover;

use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\DeadCode\PhpDoc\DeadReturnTagValueNodeAnalyzer;
Expand All @@ -16,15 +17,15 @@ public function __construct(
) {
}

public function removeReturnTagIfUseless(PhpDocInfo $phpDocInfo, ClassMethod $classMethod): bool
public function removeReturnTagIfUseless(PhpDocInfo $phpDocInfo, ClassMethod|Function_ $functionLike): bool
{
// remove existing type
$returnTagValueNode = $phpDocInfo->getReturnTagValue();
if (! $returnTagValueNode instanceof ReturnTagValueNode) {
return false;
}

$isReturnTagValueDead = $this->deadReturnTagValueNodeAnalyzer->isDead($returnTagValueNode, $classMethod);
$isReturnTagValueDead = $this->deadReturnTagValueNodeAnalyzer->isDead($returnTagValueNode, $functionLike);
if (! $isReturnTagValueDead) {
return false;
}
Expand Down
Expand Up @@ -6,6 +6,7 @@

use PhpParser\Node;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
use Rector\Core\Rector\AbstractRector;
Expand Down Expand Up @@ -65,11 +66,11 @@ public function foo(): stdClass
*/
public function getNodeTypes(): array
{
return [ClassMethod::class];
return [ClassMethod::class, Function_::class];

This comment has been minimized.

Copy link
@staabm

staabm Dec 5, 2023

Contributor

do we need the same for arrow functions?

This comment has been minimized.

Copy link
@samsonasik

samsonasik Dec 5, 2023

Author Member

Docblock is read from 2 types:

  • Stmt
  • Param

ArrowFunction is Expr that rely on parent Stmt, which seems not works iirc

}

/**
* @param ClassMethod $node
* @param ClassMethod|Function_ $node
*/
public function refactor(Node $node): ?Node
{
Expand Down

0 comments on commit 4531aeb

Please sign in to comment.