Skip to content

Commit

Permalink
Add JsonCallToExplicitJsonCallRector (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stoffo authored Jan 3, 2024
1 parent cd9d027 commit 6c9a160
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/Rector/MethodCall/JsonCallToExplicitJsonCallRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Rector\MethodCall;

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PHPStan\Type\ObjectType;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\JsonCallToExplicitJsonCallRectorTest
*/
final class JsonCallToExplicitJsonCallRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Change method calls from $this->json to $this->postJson, $this->putJson, etc.',
[
new CodeSample(
// code before
'$this->json("POST", "/api/v1/users", $data);',
// code after
'§this->postJson("/api/v1/users", $data);'
),
]
);
}

public function getNodeTypes(): array
{
return [MethodCall::class];
}

public function refactor(Node $node): ?Node
{
if ($node instanceof MethodCall) {
return $this->updateCall($node);
}

return null;
}

private function updateCall(MethodCall $methodCall): ?MethodCall
{
$methodCallName = $this->getName($methodCall->name);
if ($methodCallName === null) {
return null;
}

if (! $this->isObjectType(
$methodCall->var,
new ObjectType('Illuminate\Foundation\Testing\Concerns\MakesHttpRequests')
)) {
return null;
}

if ($methodCallName !== 'json') {
return null;
}

$arg = $methodCall->getArgs()[0];
$argValue = $arg->value;

if (! $argValue instanceof Node\Scalar\String_) {
return null;
}

$supportedMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];

if (in_array($argValue->value, $supportedMethods, true)) {
$methodCall->name = new Identifier(strtolower($argValue->value) . 'Json');
$methodCall->args = array_slice($methodCall->args, 1);

return $methodCall;
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;

class FixtureWithJsonCalls
{
public function testGet(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('get', '/');
}

public function testPost(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('post', '/');
}

public function testPut(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('put', '/');
}

public function testPatch(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('patch', '/');
}

public function testDelete(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('delete', '/');
}

public function testOptions(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('options', '/');
}
}

?>
---
<?php

namespace RectorLaravel\Tests\Rector\MethodCall\AssertStatusToAssertMethodRector\Fixture;

class FixtureWithJsonCalls
{
public function testGet(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->getJson('/');
}

public function testPost(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->postJson('/');
}

public function testPut(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->putJson('/');
}

public function testPatch(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->patchJson('/');
}

public function testDelete(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->deleteJson('/');
}

public function testOptions(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->optionsJson('/');
}
}

?>

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;

class FixtureWithJsonCalls
{
public function testHead(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('head', '/');
}

public function testTrace(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('trace', '/');
}

public function testConnect(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('connect', '/');
}
}

?>
---
<?php

namespace RectorLaravel\Tests\Rector\MethodCall\AssertStatusToAssertMethodRector\Fixture;

class FixtureWithJsonCalls
{
public function testHead(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('head', '/');
}

public function testTrace(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('trace', '/');
}

public function testConnect(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
{
$http->json('connect', '/');
}
}

?>

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class JsonCallToExplicitJsonCallRectorTest extends AbstractRectorTestCase
{
public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

/**
* @test
*/
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use RectorLaravel\Rector\MethodCall\JsonCallToExplicitJsonCallRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');

$rectorConfig->rule(JsonCallToExplicitJsonCallRector::class);
};

0 comments on commit 6c9a160

Please sign in to comment.