mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-19 06:18:07 +01:00
Merge pull request #681 from rectorphp/cq-array-search
[CodeQuality] Add SimplifyArraySearchRector
This commit is contained in:
commit
0b717b001f
36
src/NodeAnalyzer/ConstFetchAnalyzer.php
Normal file
36
src/NodeAnalyzer/ConstFetchAnalyzer.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
|
||||
/**
|
||||
* Read-only utils for ClassConstAnalyzer Node:
|
||||
* "false, true..."
|
||||
*/
|
||||
final class ConstFetchAnalyzer
|
||||
{
|
||||
public function isFalse(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof ConstFetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $node->name->toLowerString() === 'false';
|
||||
}
|
||||
|
||||
public function isTrue(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof ConstFetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $node->name->toLowerString() === 'true';
|
||||
}
|
||||
|
||||
public function isBool(Node $node): bool
|
||||
{
|
||||
return $this->isTrue($node) || $this->isFalse($node);
|
||||
}
|
||||
}
|
30
src/NodeAnalyzer/FuncCallAnalyzer.php
Normal file
30
src/NodeAnalyzer/FuncCallAnalyzer.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
|
||||
/**
|
||||
* Read-only utils for FuncCall Node:
|
||||
* "someMethod()"
|
||||
*/
|
||||
final class FuncCallAnalyzer
|
||||
{
|
||||
/**
|
||||
* Checks "specificFunction()"
|
||||
*/
|
||||
public function isName(Node $node, string $name): bool
|
||||
{
|
||||
if (! $node instanceof FuncCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $node->name instanceof Name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (string) $node->name === $name;
|
||||
}
|
||||
}
|
112
src/Rector/CodeQuality/SimplifyArraySearchRector.php
Normal file
112
src/Rector/CodeQuality/SimplifyArraySearchRector.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Rector\CodeQuality;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use Rector\NodeAnalyzer\ConstFetchAnalyzer;
|
||||
use Rector\NodeAnalyzer\FuncCallAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
final class SimplifyArraySearchRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var FuncCallAnalyzer
|
||||
*/
|
||||
private $funcCallAnalyzer;
|
||||
|
||||
/**
|
||||
* @var ConstFetchAnalyzer
|
||||
*/
|
||||
private $constFetchAnalyzer;
|
||||
|
||||
public function __construct(FuncCallAnalyzer $funcCallAnalyzer, ConstFetchAnalyzer $constFetchAnalyzer)
|
||||
{
|
||||
$this->funcCallAnalyzer = $funcCallAnalyzer;
|
||||
$this->constFetchAnalyzer = $constFetchAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition(
|
||||
'Simplify array_search to in_array',
|
||||
[
|
||||
new CodeSample(
|
||||
'array_search("searching", $array) !== false;',
|
||||
'in_array("searching", $array, true);'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Identical::class, NotIdentical::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NotIdentical $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$match = $this->matchArraySearchFuncCallAndBoolConstFetch($node);
|
||||
if ($match === null) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
[$arraySearchFuncCallNode, $boolConstFetchNode] = $match;
|
||||
|
||||
$inArrayFuncCall = new FuncCall(new Name('in_array'), [
|
||||
$arraySearchFuncCallNode->args[0],
|
||||
$arraySearchFuncCallNode->args[1],
|
||||
]);
|
||||
|
||||
if ($this->resolveIsNot($node, $boolConstFetchNode)) {
|
||||
return new BooleanNot($inArrayFuncCall);
|
||||
}
|
||||
|
||||
return $inArrayFuncCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ConstFetch[]|FuncCall[]
|
||||
*/
|
||||
private function matchArraySearchFuncCallAndBoolConstFetch(BinaryOp $binaryOpNode): ?array
|
||||
{
|
||||
if ($this->funcCallAnalyzer->isName($binaryOpNode->left, 'array_search') &&
|
||||
$this->constFetchAnalyzer->isBool($binaryOpNode->right)
|
||||
) {
|
||||
$arraySearchFuncCallNode = $binaryOpNode->left;
|
||||
$boolConstFetchNode = $binaryOpNode->right;
|
||||
} elseif ($this->constFetchAnalyzer->isBool($binaryOpNode->left) &&
|
||||
$this->funcCallAnalyzer->isName($binaryOpNode->right, 'array_search')
|
||||
) {
|
||||
$arraySearchFuncCallNode = $binaryOpNode->right;
|
||||
$boolConstFetchNode = $binaryOpNode->left;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [$arraySearchFuncCallNode, $boolConstFetchNode];
|
||||
}
|
||||
|
||||
private function resolveIsNot(BinaryOp $node, ConstFetch $boolConstFetchNode): bool
|
||||
{
|
||||
if ($node instanceof Identical) {
|
||||
return $this->constFetchAnalyzer->isFalse($boolConstFetchNode);
|
||||
}
|
||||
|
||||
return $this->constFetchAnalyzer->isTrue($boolConstFetchNode);
|
||||
}
|
||||
}
|
@ -4,14 +4,14 @@ namespace Rector\Rector\CodeQuality;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BinaryOp\Equal;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotEqual;
|
||||
use PhpParser\Node\Expr\BinaryOp\Greater;
|
||||
use PhpParser\Node\Expr\BinaryOp\GreaterOrEqual;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotEqual;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BinaryOp\Smaller;
|
||||
use PhpParser\Node\Expr\BinaryOp\SmallerOrEqual;
|
||||
use PhpParser\Node\Expr\BinaryOp\GreaterOrEqual;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
|
@ -0,0 +1,17 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
if (in_array('searching', $array)) {
|
||||
echo 'yes!';
|
||||
}
|
||||
|
||||
if (in_array('searching', $array)) {
|
||||
echo 'yes!';
|
||||
}
|
||||
|
||||
if (!in_array('searching', $array)) {
|
||||
echo 'no!';
|
||||
}
|
||||
|
||||
if (!in_array('searching', $array)) {
|
||||
echo 'no!';
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\CodeQuality\SimplifyArraySearchRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
/**
|
||||
* @covers \Rector\Rector\CodeQuality\SimplifyArraySearchRector
|
||||
*/
|
||||
final class SimplifyArraySearchRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideWrongToFixedFiles()
|
||||
*/
|
||||
public function test(string $wrong, string $fixed): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent($wrong, $fixed);
|
||||
}
|
||||
|
||||
public function provideWrongToFixedFiles(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'];
|
||||
}
|
||||
|
||||
protected function provideConfig(): string
|
||||
{
|
||||
return __DIR__ . '/config.yml';
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
if (array_search('searching', $array) !== false) {
|
||||
echo 'yes!';
|
||||
}
|
||||
|
||||
if (array_search('searching', $array) === true) {
|
||||
echo 'yes!';
|
||||
}
|
||||
|
||||
if (array_search('searching', $array) === false) {
|
||||
echo 'no!';
|
||||
}
|
||||
|
||||
if (array_search('searching', $array) !== true) {
|
||||
echo 'no!';
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
services:
|
||||
Rector\Rector\CodeQuality\SimplifyArraySearchRector: ~
|
Loading…
x
Reference in New Issue
Block a user