Skip to content

Commit

Permalink
Remove parent node look up from ReturnTypeFromStrictTypedCallRector (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Jun 10, 2023
1 parent a394e5e commit 65765cf
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 174 deletions.
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ parameters:
- src/Bootstrap/ExtensionConfigResolver.php
- src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php
- src/DependencyInjection/DefinitionFinder.php
- config/config.php

# use of internal phpstan classes
-
Expand Down Expand Up @@ -702,7 +703,6 @@ parameters:
- '#Cognitive complexity for "Rector\\Transform\\Rector\\StaticCall\\StaticCallToMethodCallRector\:\:refactorWithScope\(\)" is 14, keep it under 11#'
- '#Cognitive complexity for "Rector\\TypeDeclaration\\Rector\\ClassMethod\\ParamTypeByMethodCallTypeRector\:\:refactorWithScope\(\)" is 13, keep it under 11#'

- '#Function "class_exists\(\)" cannot be used/left in the code\: use ReflectionProvider\->has\*\(\) instead#'
- '#Cognitive complexity for "Rector\\Php81\\Rector\\Property\\ReadOnlyPropertyRector\:\:refactorWithScope\(\)" is 12, keep it under 11#'

- '#Parameter \#2 \$callable of method Rector\\Core\\Rector\\AbstractRector\:\:traverseNodesWithCallable\(\) expects callable\(PhpParser\\Node\)\: \(int\|PhpParser\\Node\|null\), Closure\(PhpParser\\Node\)\: \(array<PhpParser\\Node\\Stmt>\|int\|null\) given#'

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,11 @@ public function refactor(Node $node): ?Node
}

$type = $this->getType($node->expr);

if ($type->isVoid()->yes()) {
return null;
}

$returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($type, TypeKind::RETURN);

if ($returnTypeNode === null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use PhpParser\Node;
use PhpParser\Node\ComplexType;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Identifier;
Expand All @@ -17,14 +17,14 @@
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\Node\UnionType as PhpParserUnionType;
use PhpParser\NodeTraverser;
use PHPStan\Analyser\Scope;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\UnionType;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\TypeDeclaration\NodeAnalyzer\TypeNodeUnwrapper;
use Rector\TypeDeclaration\TypeAnalyzer\ReturnStrictTypeAnalyzer;
use Rector\TypeDeclaration\TypeInferer\ReturnTypeInferer;
Expand Down Expand Up @@ -89,7 +89,7 @@ private function getNumber(): int
*/
public function getNodeTypes(): array
{
return [ClassMethod::class, Function_::class, Closure::class, ArrowFunction::class];
return [ClassMethod::class, Function_::class, Closure::class];
}

public function provideMinPhpVersion(): int
Expand All @@ -98,46 +98,27 @@ public function provideMinPhpVersion(): int
}

/**
* @param ClassMethod|Function_|Closure|ArrowFunction $node
* @param ClassMethod|Function_|Closure $node
*/
public function refactorWithScope(Node $node, Scope $scope): ?Node
{
if ($this->isSkipped($node, $scope)) {
if ($node->stmts === null) {
return null;
}

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

/** @var Return_[] $returns */
$returns = $this->betterNodeFinder->find((array) $node->stmts, function (Node $subNode) use ($node): bool {
$currentFunctionLike = $this->betterNodeFinder->findParentType($subNode, FunctionLike::class);

if ($currentFunctionLike === $node) {
return $subNode instanceof Return_;
}

$currentReturn = $this->betterNodeFinder->findParentType($subNode, Return_::class);
if (! $currentReturn instanceof Return_) {
return false;
}
$currentScopeReturns = $this->findCurrentScopeReturns($node);

$currentReturnFunctionLike = $this->betterNodeFinder->findParentType($currentReturn, FunctionLike::class);
if ($currentReturnFunctionLike !== $currentFunctionLike) {
return false;
}

return $subNode instanceof Return_;
});

$returnedStrictTypes = $this->returnStrictTypeAnalyzer->collectStrictReturnTypes($returns);
$returnedStrictTypes = $this->returnStrictTypeAnalyzer->collectStrictReturnTypes($currentScopeReturns);
if ($returnedStrictTypes === []) {
return null;
}

if (count($returnedStrictTypes) === 1) {
return $this->refactorSingleReturnType($returns[0], $returnedStrictTypes[0], $node);
return $this->refactorSingleReturnType($currentScopeReturns[0], $returnedStrictTypes[0], $node);
}

if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_TYPES)) {
Expand All @@ -151,25 +132,6 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
return null;
}

private function processArrowFunction(ArrowFunction $arrowFunction): ?ArrowFunction
{
$resolvedType = $this->nodeTypeResolver->getType($arrowFunction->expr);

// void type is not accepted for arrow functions - https://www.php.net/manual/en/functions.arrow.php#125673
if ($resolvedType->isVoid()->yes()) {
return null;
}

$returnType = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($resolvedType, TypeKind::RETURN);

if (! $returnType instanceof Node) {
return null;
}

$arrowFunction->returnType = $returnType;
return $arrowFunction;
}

private function isUnionPossibleReturnsVoid(ClassMethod | Function_ | Closure $node): bool
{
$inferReturnType = $this->returnTypeInferer->inferFunctionLike($node);
Expand Down Expand Up @@ -198,29 +160,23 @@ private function processSingleUnionType(
return $node;
}

private function isSkipped(ClassMethod | Function_ | Closure | ArrowFunction $node, Scope $scope): bool
private function shouldSkip(ClassMethod | Function_ | Closure $node, Scope $scope): bool
{
if ($node instanceof ArrowFunction) {
return $node->returnType !== null;
}

if ($node->returnType !== null) {
return true;
}

if (! $node instanceof ClassMethod) {
return $this->isUnionPossibleReturnsVoid($node);
}

if ($this->classMethodReturnTypeOverrideGuard->shouldSkipClassMethod($node, $scope)) {
return true;
}
if ($node instanceof ClassMethod) {
if ($this->classMethodReturnTypeOverrideGuard->shouldSkipClassMethod($node, $scope)) {
return true;
}

if (! $node->isMagic()) {
return $this->isUnionPossibleReturnsVoid($node);
if ($node->isMagic()) {
return true;
}
}

return true;
return $this->isUnionPossibleReturnsVoid($node);
}

private function refactorSingleReturnType(
Expand All @@ -247,4 +203,35 @@ private function refactorSingleReturnType(

return $functionLike;
}

/**
* @return Return_[]
*/
private function findCurrentScopeReturns(ClassMethod|Function_|Closure $node): array
{
$currentScopeReturns = [];

if ($node->stmts === null) {
return [];
}

$this->traverseNodesWithCallable($node->stmts, static function (Node $node) use (&$currentScopeReturns): ?int {
// skip scope nesting
if ($node instanceof FunctionLike) {
return NodeTraverser::STOP_TRAVERSAL;
}

if (! $node instanceof Return_) {
return null;
}

if (! $node->expr instanceof Expr) {
return null;
}

$currentScopeReturns[] = $node;
return null;
});
return $currentScopeReturns;
}
}

0 comments on commit 65765cf

Please sign in to comment.