Skip to content

Commit

Permalink
Make JsonThrowOnErrorRector work with local scope to detect error_jso…
Browse files Browse the repository at this point in the history
…n methods (#4451)
  • Loading branch information
TomasVotruba committed Jul 9, 2023
1 parent cfc88dc commit d706d34
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 40 deletions.

This file was deleted.

65 changes: 40 additions & 25 deletions rules/Php73/Rector/FuncCall/JsonThrowOnErrorRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\LNumber;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
Expand All @@ -24,6 +25,8 @@
*/
final class JsonThrowOnErrorRector extends AbstractRector implements MinPhpVersionInterface
{
private bool $hasChanged = false;

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
Expand All @@ -49,24 +52,48 @@ public function getRuleDefinition(): RuleDefinition
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
return [StmtsAwareInterface::class];
}

/**
* @param FuncCall $node
* @param StmtsAwareInterface $node
*/
public function refactor(Node $node): ?Node
{
if ($this->shouldSkip($node)) {
// if found, skip it :)
$hasJsonErrorFuncCall = (bool) $this->betterNodeFinder->findFirst(
$node,
fn (Node $node): bool => $this->isNames($node, ['json_last_error', 'json_last_error_msg'])
);

if ($hasJsonErrorFuncCall) {
return null;
}

if ($this->isName($node, 'json_encode')) {
return $this->processJsonEncode($node);
}
$this->hasChanged = false;

$this->traverseNodesWithCallable($node, function (Node $currentNode): ?FuncCall {
if (! $currentNode instanceof FuncCall) {
return null;
}

if ($this->shouldSkipFuncCall($currentNode)) {
return null;
}

if ($this->isName($currentNode, 'json_encode')) {
return $this->processJsonEncode($currentNode);
}

if ($this->isName($currentNode, 'json_decode')) {
return $this->processJsonDecode($currentNode);
}

return null;
});

if ($this->isName($node, 'json_decode')) {
return $this->processJsonDecode($node);
if ($this->hasChanged) {
return $node;
}

return null;
Expand All @@ -77,12 +104,8 @@ public function provideMinPhpVersion(): int
return PhpVersionFeature::JSON_EXCEPTION;
}

private function shouldSkip(FuncCall $funcCall): bool
private function shouldSkipFuncCall(FuncCall $funcCall): bool
{
if (! $this->isNames($funcCall, ['json_encode', 'json_decode'])) {
return true;
}

if ($funcCall->isFirstClassCallable()) {
return true;
}
Expand All @@ -101,17 +124,7 @@ private function shouldSkip(FuncCall $funcCall): bool
}
}

if ($this->isFirstValueStringOrArray($funcCall)) {
return true;
}

return (bool) $this->betterNodeFinder->findFirstNext($funcCall, function (Node $node): bool {
if (! $node instanceof FuncCall) {
return false;
}

return $this->isNames($node, ['json_last_error', 'json_last_error_msg']);
});
return $this->isFirstValueStringOrArray($funcCall);
}

private function processJsonEncode(FuncCall $funcCall): ?FuncCall
Expand All @@ -120,8 +133,9 @@ private function processJsonEncode(FuncCall $funcCall): ?FuncCall
return null;
}

$funcCall->args[1] = new Arg($this->createConstFetch('JSON_THROW_ON_ERROR'));
$this->hasChanged = true;

$funcCall->args[1] = new Arg($this->createConstFetch('JSON_THROW_ON_ERROR'));
return $funcCall;
}

Expand All @@ -140,6 +154,7 @@ private function processJsonDecode(FuncCall $funcCall): ?FuncCall
$funcCall->args[2] = new Arg(new LNumber(512));
}

$this->hasChanged = true;
$funcCall->args[3] = new Arg($this->createConstFetch('JSON_THROW_ON_ERROR'));

return $funcCall;
Expand Down

0 comments on commit d706d34

Please sign in to comment.