Skip to content

Commit

Permalink
[DowngradePhp80] Remove self return type if child already has no retu…
Browse files Browse the repository at this point in the history
…rn type (#725)

* [DowngradePhp80] Remove self return type if child already has no return type

* comment

* fix

* clean up

* phpstan
  • Loading branch information
samsonasik committed Aug 20, 2021
1 parent 3c8f8a0 commit ceb4930
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 5 deletions.
10 changes: 10 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,13 @@ parameters:
paths:
- rules/Php72/Rector/Assign/ReplaceEachAssignmentWithKeyCurrentRector.php

-
message: '#foreach\(\), while\(\), for\(\) or if\(\) cannot contain a complex expression\. Extract it to a new variable on a line before#'
paths:
- packages/NodeNestingScope/FlowOfControlLocator.php
- packages/NodeNestingScope/ParentFinder.php
- rules/CodeQuality/Rector/Return_/SimplifyUselessVariableRector.php
- rules/CodingStyle/Rector/Assign/ManualJsonStringToJsonEncodeArrayRector.php
- rules/Php70/Rector/FuncCall/MultiDirnameRector.php
- src/Application/FileProcessor.php
- src/PhpParser/Node/BetterNodeFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Rector\Tests\DowngradePhp80\Rector\ClassMethod\DowngradeStaticTypeDeclarationRector\Fixture;

interface RemoveSelfChildAlreadyNoType
{
public function run(): self;
}

class Child implements RemoveSelfChildAlreadyNoType
{
// return type may removed by other rules
// @see https://github.com/rectorphp/rector/issues/6652
public function run()
{

}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp80\Rector\ClassMethod\DowngradeStaticTypeDeclarationRector\Fixture;

interface RemoveSelfChildAlreadyNoType
{
/**
* @return $this
*/
public function run();
}

class Child implements RemoveSelfChildAlreadyNoType
{
// return type may removed by other rules
// @see https://github.com/rectorphp/rector/issues/6652
public function run()
{

}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\StaticType;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\DowngradePhp71\TypeDeclaration\PhpDocFromTypeDeclarationDecorator;
use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
Expand All @@ -23,7 +26,9 @@ final class DowngradeStaticTypeDeclarationRector extends AbstractRector
{
public function __construct(
private PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator,
private ReflectionProvider $reflectionProvider
private ReflectionProvider $reflectionProvider,
private AstResolver $astResolver,
private FamilyRelationsAnalyzer $familyRelationsAnalyzer
) {
}

Expand Down Expand Up @@ -73,10 +78,9 @@ public function getStatic()
*/
public function refactor(Node $node): ?Node
{
if ($node->returnType instanceof Name && $this->nodeNameResolver->isName(
$node->returnType,
'self'
)) {
$scope = $node->getAttribute(AttributeKey::SCOPE);

if ($scope instanceof Scope && $this->shouldSkip($node, $scope)) {
return null;
}

Expand Down Expand Up @@ -104,4 +108,49 @@ public function refactor(Node $node): ?Node

return $node;
}

private function shouldSkip(ClassMethod $classMethod, Scope $scope): bool
{
if (! $classMethod->returnType instanceof Name) {
return false;
}

if (! $this->nodeNameResolver->isName($classMethod->returnType, 'self')) {
return false;
}

$classLike = $classMethod->getAttribute(AttributeKey::CLASS_NODE);
$className = $this->nodeNameResolver->getName($classLike);

if ($className === null) {
return false;
}

if (! $this->reflectionProvider->hasClass($className)) {
return false;
}

$classReflection = $this->reflectionProvider->getClass($className);
$methodName = $this->nodeNameResolver->getName($classMethod);
$children = $this->familyRelationsAnalyzer->getChildrenOfClassReflection($classReflection);

foreach ($children as $child) {
if (! $child->hasMethod($methodName)) {
continue;
}

$method = $child->getMethod($methodName, $scope);
$classMethod = $this->astResolver->resolveClassMethodFromMethodReflection($method);

if (! $classMethod instanceof ClassMethod) {
continue;
}

if ($classMethod->returnType === null) {
return false;
}
}

return true;
}
}

0 comments on commit ceb4930

Please sign in to comment.