From 31a019b0d7f9424f7c2ea63c273ef2b9ba30b132 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Tue, 30 Jun 2020 21:09:11 +0200 Subject: [PATCH] add constant return array support --- .../src/NodeFactory/ThisRenderFactory.php | 12 ++-- .../TemplateAnnotationToThisRenderRector.php | 72 +++++++++++-------- .../Fixture/empty_body.php.inc | 35 +++++++++ .../Fixture/if_else_array_response.php.inc | 60 ++++++++++++++++ .../Fixture/try_catch_array_response.php.inc | 52 ++++++++++++++ .../Fixture/with_only_vars.php.inc | 3 +- 6 files changed, 199 insertions(+), 35 deletions(-) create mode 100755 rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/empty_body.php.inc create mode 100755 rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/if_else_array_response.php.inc create mode 100755 rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/try_catch_array_response.php.inc diff --git a/rules/sensio/src/NodeFactory/ThisRenderFactory.php b/rules/sensio/src/NodeFactory/ThisRenderFactory.php index 84db899190f..3ac8d85c6e2 100644 --- a/rules/sensio/src/NodeFactory/ThisRenderFactory.php +++ b/rules/sensio/src/NodeFactory/ThisRenderFactory.php @@ -80,7 +80,9 @@ final class ThisRenderFactory ?Return_ $return, SensioTemplateTagValueNode $sensioTemplateTagValueNode ): array { - $arguments = [$this->resolveTemplateName($classMethod, $sensioTemplateTagValueNode)]; + $templateNameString = $this->resolveTemplateName($classMethod, $sensioTemplateTagValueNode); + + $arguments = [$templateNameString]; $parametersExpr = $this->resolveParametersExpr($return, $sensioTemplateTagValueNode); if ($parametersExpr !== null) { @@ -118,6 +120,10 @@ final class ThisRenderFactory ?Return_ $return, SensioTemplateTagValueNode $sensioTemplateTagValueNode ): ?Expr { + if ($sensioTemplateTagValueNode->getVars() !== []) { + return $this->createArrayFromVars($sensioTemplateTagValueNode->getVars()); + } + if ($return === null) { return null; } @@ -139,10 +145,6 @@ final class ThisRenderFactory return $this->arrayFromCompactFactory->createArrayFromCompactFuncCall($compactFunCall); } - if ($sensioTemplateTagValueNode->getVars() !== []) { - return $this->createArrayFromVars($sensioTemplateTagValueNode->getVars()); - } - return null; } } diff --git a/rules/sensio/src/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector.php b/rules/sensio/src/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector.php index b9918de11a3..8891a529db6 100644 --- a/rules/sensio/src/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector.php +++ b/rules/sensio/src/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector.php @@ -16,6 +16,7 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Return_; use PHPStan\Type\ArrayType; +use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; use Rector\BetterPhpDocParser\PhpDocNode\Sensio\SensioTemplateTagValueNode; use Rector\Core\Rector\AbstractRector; @@ -158,34 +159,23 @@ PHP ClassMethod $classMethod, SensioTemplateTagValueNode $sensioTemplateTagValueNode ): void { + /** @var Return_[] $returns */ + $returns = $this->betterNodeFinder->findInstanceOf((array) $classMethod->stmts, Return_::class); $hasThisRenderOrReturnsResponse = $this->hasLastReturnResponse($classMethod); - /** @var Return_|null $lastReturn */ - $lastReturn = $this->betterNodeFinder->findLastInstanceOf((array) $classMethod->stmts, Return_::class); - - // nothing we can do - if ($lastReturn !== null && $lastReturn->expr === null) { - return; + foreach ($returns as $return) { + $this->refactorReturn($return, $classMethod, $sensioTemplateTagValueNode, $hasThisRenderOrReturnsResponse); } - // create "$this->render('template.file.twig.html', ['key' => 'value']);" method call - $thisRenderMethodCall = $this->thisRenderFactory->create( - $classMethod, - $lastReturn, - $sensioTemplateTagValueNode - ); + if (count($returns) === 0) { + $thisRenderMethodCall = $this->thisRenderFactory->create( + $classMethod, + null, + $sensioTemplateTagValueNode + ); - if ($lastReturn === null) { $this->refactorNoReturn($classMethod, $thisRenderMethodCall); - return; } - - $this->refactorReturnWithValue( - $lastReturn, - $hasThisRenderOrReturnsResponse, - $thisRenderMethodCall, - $classMethod - ); } private function processClassMethodWithoutReturn( @@ -235,22 +225,22 @@ PHP } private function refactorReturnWithValue( - Return_ $lastReturn, + Return_ $return, bool $hasThisRenderOrReturnsResponse, MethodCall $thisRenderMethodCall, ClassMethod $classMethod ): void { /** @var Expr $lastReturnExpr */ - $lastReturnExpr = $lastReturn->expr; + $lastReturnExpr = $return->expr; $returnStaticType = $this->getStaticType($lastReturnExpr); - if (! $lastReturn->expr instanceof MethodCall) { - if (! $hasThisRenderOrReturnsResponse) { - $lastReturn->expr = $thisRenderMethodCall; + if (! $return->expr instanceof MethodCall) { + if (! $hasThisRenderOrReturnsResponse || $returnStaticType instanceof ConstantArrayType) { + $return->expr = $thisRenderMethodCall; } } elseif ($returnStaticType instanceof ArrayType) { - $lastReturn->expr = $thisRenderMethodCall; + $return->expr = $thisRenderMethodCall; } elseif ($returnStaticType instanceof MixedType) { // nothing we can do return; @@ -262,10 +252,36 @@ PHP ); if ($isArrayOrResponseType) { - $this->processIsArrayOrResponseType($lastReturn, $lastReturnExpr, $thisRenderMethodCall); + $this->processIsArrayOrResponseType($return, $lastReturnExpr, $thisRenderMethodCall); } $this->returnTypeDeclarationUpdater->updateClassMethod($classMethod, self::RESPONSE_CLASS); $this->removePhpDocTagValueNode($classMethod, SensioTemplateTagValueNode::class); } + + private function refactorReturn( + Return_ $return, + ClassMethod $classMethod, + SensioTemplateTagValueNode $sensioTemplateTagValueNode, + bool $hasThisRenderOrReturnsResponse + ): void { + // nothing we can do + if ($return->expr === null) { + return; + } + + // create "$this->render('template.file.twig.html', ['key' => 'value']);" method call + $thisRenderMethodCall = $this->thisRenderFactory->create( + $classMethod, + $return, + $sensioTemplateTagValueNode + ); + + $this->refactorReturnWithValue( + $return, + $hasThisRenderOrReturnsResponse, + $thisRenderMethodCall, + $classMethod + ); + } } diff --git a/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/empty_body.php.inc b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/empty_body.php.inc new file mode 100755 index 00000000000..3ce4224f0da --- /dev/null +++ b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/empty_body.php.inc @@ -0,0 +1,35 @@ + +----- +render('@App/empty_body/index.html.twig'); + } +} + +?> diff --git a/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/if_else_array_response.php.inc b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/if_else_array_response.php.inc new file mode 100755 index 00000000000..cbcb836e524 --- /dev/null +++ b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/if_else_array_response.php.inc @@ -0,0 +1,60 @@ + 'value' + ]; + } elseif (mt_rand(0, 200)) { + return [ + 'key' => 'value2' + ]; + } else { + return new RedirectResponse('here'); + } + } +} + +?> +----- +render('@App/class_if_else_array/index.html.twig', [ + 'key' => 'value' + ]); + } elseif (mt_rand(0, 200)) { + return $this->render('@App/class_if_else_array/index.html.twig', [ + 'key' => 'value2' + ]); + } else { + return new RedirectResponse('here'); + } + } +} + +?> diff --git a/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/try_catch_array_response.php.inc b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/try_catch_array_response.php.inc new file mode 100755 index 00000000000..af27eb16c2b --- /dev/null +++ b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/try_catch_array_response.php.inc @@ -0,0 +1,52 @@ + 'value' + ]; + } catch (Throwable $throwable) { + return new RedirectResponse('here'); + } + } +} + +?> +----- +render('@App/class_try_catch_array_response/index.html.twig', [ + 'key' => 'value' + ]); + } catch (Throwable $throwable) { + return new RedirectResponse('here'); + } + } +} + +?> diff --git a/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/with_only_vars.php.inc b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/with_only_vars.php.inc index 1ba1c6c4c96..bb8a461cb89 100755 --- a/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/with_only_vars.php.inc +++ b/rules/sensio/tests/Rector/FrameworkExtraBundle/TemplateAnnotationToThisRenderRector/Fixture/with_only_vars.php.inc @@ -10,9 +10,8 @@ class WithOnlyVarsController extends AbstractController /** * @Template(vars={"post"}) */ - public function index(Post $post): array + public function index(Post $post) { - return []; } }