[TypeDeclaration] Skip controller render method on @var to type declaratoin (#1576)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Tomas Votruba 2021-12-27 12:19:52 +01:00 committed by GitHub
parent 889a682d12
commit 68dde1af51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 2 deletions

View File

@ -0,0 +1,15 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector\Fixture;
use Nette\Application\UI\Presenter;
final class SkipNetteRenderMethod extends Presenter
{
/**
* @param int $id
*/
public function render($id)
{
}
}

View File

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Rector\TypeDeclaration\NodeAnalyzer;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
use Symplify\Astral\Naming\SimpleNameResolver;
final class ControllerRenderMethodAnalyzer
{
public function __construct(
private readonly SimpleNameResolver $simpleNameResolver,
private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer
) {
}
public function isRenderMethod(ClassMethod $classMethod, Scope $scope): bool
{
// nette one?
$classReflection = $scope->getClassReflection();
if (! $classReflection instanceof ClassReflection) {
return false;
}
if ($this->isNetteRenderMethod($classReflection, $classMethod)) {
return true;
}
return $this->isSymfonyRenderMethod($classReflection, $classMethod);
}
private function isNetteRenderMethod(ClassReflection $classReflection, ClassMethod $classMethod): bool
{
if (! $classReflection->isSubclassOf('Nette\Application\UI\Control')) {
return false;
}
if (! $classMethod->isPublic()) {
return false;
}
return $this->simpleNameResolver->isNames($classMethod->name, ['render*', 'handle*', 'action*']);
}
private function isSymfonyRenderMethod(ClassReflection $classReflection, ClassMethod $classMethod): bool
{
if (! $classReflection->isSubclassOf(
'Symfony\Bundle\FrameworkBundle\Controller\Controller'
) && ! $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\AbstractController')) {
return false;
}
if (! $classMethod->isPublic()) {
return false;
}
if ($this->simpleNameResolver->isNames($classMethod->name, ['__invoke', '*render'])) {
return true;
}
return $this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, 'Symfony\Component\Routing\Annotation\Route');
}
}

View File

@ -10,6 +10,7 @@ use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Interface_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\UnionType;
@ -19,6 +20,7 @@ use Rector\DeadCode\PhpDoc\TagRemover\ParamTagRemover;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\StaticTypeMapper\ValueObject\Type\NonExistingObjectType;
use Rector\TypeDeclaration\NodeAnalyzer\ControllerRenderMethodAnalyzer;
use Rector\TypeDeclaration\NodeTypeAnalyzer\TraitTypeAnalyzer;
use Rector\TypeDeclaration\TypeInferer\ParamTypeInferer;
use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard;
@ -46,7 +48,8 @@ final class ParamTypeDeclarationRector extends AbstractRector implements MinPhpV
private readonly ParamTypeInferer $paramTypeInferer,
private readonly TraitTypeAnalyzer $traitTypeAnalyzer,
private readonly ParamTagRemover $paramTagRemover,
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard,
private readonly ControllerRenderMethodAnalyzer $controllerRenderMethodAnalyzer,
) {
}
@ -135,6 +138,14 @@ CODE_SAMPLE
return null;
}
$scope = $node->getAttribute(AttributeKey::SCOPE);
if ($node instanceof ClassMethod && $scope instanceof Scope && $this->controllerRenderMethodAnalyzer->isRenderMethod(
$node,
$scope
)) {
return null;
}
foreach ($node->params as $position => $param) {
$this->refactorParam($param, $position, $node);
}

View File

@ -8,6 +8,6 @@ if (class_exists('Nette\Application\UI\Presenter')) {
return;
}
class Presenter
class Presenter extends Control
{
}