Merge pull request #3622 from rectorphp/template-try-catch-array

[Symfony] add constant return array support to TemplateAnnotationToThisRenderRector
This commit is contained in:
kodiakhq[bot] 2020-06-30 19:40:23 +00:00 committed by GitHub
commit af18b50377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 199 additions and 35 deletions

View File

@ -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;
}
}

View File

@ -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
);
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class EmptyBodyController extends AbstractController
{
/**
* @Template
*/
public function indexAction()
{
}
}
?>
-----
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class EmptyBodyController extends AbstractController
{
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
return $this->render('@App/empty_body/index.html.twig');
}
}
?>

View File

@ -0,0 +1,60 @@
<?php declare (strict_types=1);
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Throwable;
class ClassIfElseArrayController extends AbstractController
{
/**
* @Template()
*/
public function indexAction()
{
if (mt_rand(0, 100)) {
return [
'key' => 'value'
];
} elseif (mt_rand(0, 200)) {
return [
'key' => 'value2'
];
} else {
return new RedirectResponse('here');
}
}
}
?>
-----
<?php declare (strict_types=1);
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Throwable;
class ClassIfElseArrayController extends AbstractController
{
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
if (mt_rand(0, 100)) {
return $this->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');
}
}
}
?>

View File

@ -0,0 +1,52 @@
<?php declare (strict_types=1);
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Throwable;
class ClassTryCatchArrayResponseController extends AbstractController
{
/**
* @Template()
*/
public function indexAction()
{
try {
return [
'key' => 'value'
];
} catch (Throwable $throwable) {
return new RedirectResponse('here');
}
}
}
?>
-----
<?php declare (strict_types=1);
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Throwable;
class ClassTryCatchArrayResponseController extends AbstractController
{
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
try {
return $this->render('@App/class_try_catch_array_response/index.html.twig', [
'key' => 'value'
]);
} catch (Throwable $throwable) {
return new RedirectResponse('here');
}
}
}
?>

View File

@ -10,9 +10,8 @@ class WithOnlyVarsController extends AbstractController
/**
* @Template(vars={"post"})
*/
public function index(Post $post): array
public function index(Post $post)
{
return [];
}
}