Skip to content

Commit 3234dd8

Browse files
authored
Keep JsonResponse type (#757)
1 parent 9f83efb commit 3234dd8

6 files changed

Lines changed: 111 additions & 4 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\CodeQuality\Rector\ClassMethod\TemplateAnnotationToThisRenderRector\Fixture\Attributes;
4+
5+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
6+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
7+
use Symfony\Component\HttpFoundation\JsonResponse;
8+
use Symfony\Component\HttpFoundation\Response;
9+
10+
final class RemoveAttributeButKeepJsonResponse extends AbstractController
11+
{
12+
#[Template("with_some_template.twig")]
13+
public function indexAction(): array|Response
14+
{
15+
if (mt_rand(0, 1)) {
16+
return ['key' => 'value'];
17+
}
18+
19+
return new JsonResponse([], Response::HTTP_BAD_REQUEST);
20+
}
21+
}
22+
23+
?>
24+
-----
25+
<?php
26+
27+
namespace Rector\Symfony\Tests\CodeQuality\Rector\ClassMethod\TemplateAnnotationToThisRenderRector\Fixture\Attributes;
28+
29+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
30+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
31+
use Symfony\Component\HttpFoundation\JsonResponse;
32+
use Symfony\Component\HttpFoundation\Response;
33+
34+
final class RemoveAttributeButKeepJsonResponse extends AbstractController
35+
{
36+
public function indexAction(): \Symfony\Component\HttpFoundation\Response
37+
{
38+
if (mt_rand(0, 1)) {
39+
return $this->render('with_some_template.twig', ['key' => 'value']);
40+
}
41+
return new JsonResponse([], Response::HTTP_BAD_REQUEST);
42+
}
43+
}
44+
45+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\CodeQuality\Rector\ClassMethod\TemplateAnnotationToThisRenderRector\Fixture\Attributes;
4+
5+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
6+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
7+
use Symfony\Component\HttpFoundation\JsonResponse;
8+
use Symfony\Component\HttpFoundation\Response;
9+
10+
final class RemoveAttributeButKeepJsonResponseReversed extends AbstractController
11+
{
12+
#[Template("with_some_template.twig")]
13+
public function indexAction(): array|Response
14+
{
15+
if (mt_rand(0, 1)) {
16+
return new JsonResponse([], Response::HTTP_BAD_REQUEST);
17+
}
18+
19+
return ['key' => 'value'];
20+
}
21+
}
22+
23+
?>
24+
-----
25+
<?php
26+
27+
namespace Rector\Symfony\Tests\CodeQuality\Rector\ClassMethod\TemplateAnnotationToThisRenderRector\Fixture\Attributes;
28+
29+
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
30+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
31+
use Symfony\Component\HttpFoundation\JsonResponse;
32+
use Symfony\Component\HttpFoundation\Response;
33+
34+
final class RemoveAttributeButKeepJsonResponseReversed extends AbstractController
35+
{
36+
public function indexAction(): \Symfony\Component\HttpFoundation\Response
37+
{
38+
if (mt_rand(0, 1)) {
39+
return new JsonResponse([], Response::HTTP_BAD_REQUEST);
40+
}
41+
return $this->render('with_some_template.twig', ['key' => 'value']);
42+
}
43+
}
44+
45+
?>

rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Symfony\CodeQuality\Rector\ClassMethod;
66

7+
use PhpParser\Node\Expr\New_;
78
use PhpParser\Node;
89
use PhpParser\Node\Attribute;
910
use PhpParser\Node\Expr;
@@ -38,6 +39,7 @@
3839
use Rector\Symfony\NodeFinder\EmptyReturnNodeFinder;
3940
use Rector\Symfony\TypeAnalyzer\ArrayUnionResponseTypeAnalyzer;
4041
use Rector\Symfony\TypeDeclaration\ReturnTypeDeclarationUpdater;
42+
use Symfony\Component\HttpFoundation\Response;
4143
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
4244
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
4345

@@ -201,7 +203,6 @@ private function refactorClassMethod(
201203
$classMethod,
202204
&$hasChanged
203205
): ?int {
204-
205206
// keep as similar type
206207
if ($node instanceof Closure || $node instanceof Function_) {
207208
return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
@@ -312,7 +313,14 @@ private function refactorReturnWithValue(
312313

313314
$returnStaticType = $this->getType($lastReturnExpr);
314315

315-
if (! $return->expr instanceof MethodCall) {
316+
// is new response? keep it
317+
$isResponseType = false;
318+
if ($return->expr instanceof New_) {
319+
$new = $return->expr;
320+
if ($this->isObjectType($new->class, new ObjectType(Response::class))) {
321+
$isResponseType = true;
322+
}
323+
} elseif (! $return->expr instanceof MethodCall) {
316324
if (! $hasThisRenderOrReturnsResponse || $returnStaticType instanceof ConstantArrayType) {
317325
$return->expr = $thisRenderMethodCall;
318326
}
@@ -329,13 +337,14 @@ private function refactorReturnWithValue(
329337
);
330338

331339
// skip as the original class method has to change first
332-
if ($isArrayOrResponseType) {
340+
if ($isArrayOrResponseType && $isResponseType === false) {
333341
return false;
334342
}
335343

336344
// already response
337345
$this->removeDoctrineAnnotationTagValueNode($classMethod, $doctrineTagValueNodeOrAttribute);
338346
$this->returnTypeDeclarationUpdater->updateClassMethod($classMethod, SymfonyClass::RESPONSE);
347+
339348
return true;
340349
}
341350

src/NodeFactory/Annotations/AnnotationOrAttributeValueResolver.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Rector\Symfony\NodeFactory\Annotations;
66

7+
use PhpParser\Node\Identifier;
78
use PhpParser\Node\Arg;
89
use PhpParser\Node\Attribute;
910
use PhpParser\Node\Scalar\String_;
@@ -64,7 +65,7 @@ public function resolve(
6465

6566
private function isKeyEmptyOrMatch(Arg $attributeArg, string $desiredKey): bool
6667
{
67-
if ($attributeArg->name === null) {
68+
if (!$attributeArg->name instanceof Identifier) {
6869
return true;
6970
}
7071

stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Template.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@
55
#[\Attribute]
66
class Template
77
{
8+
public function __construct(string $templatePath)
9+
{
10+
11+
}
812
}

stubs/Symfony/Component/HttpFoundation/JsonResponse.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@
88

99
class JsonResponse extends Response
1010
{
11+
public function __construct(array $items, int $status = 200, array $headers = [], bool $json = false)
12+
{
13+
}
1114
}

0 commit comments

Comments
 (0)