[CodeQuality] Add SimplifyArraySearchRector

This commit is contained in:
Tomas Votruba 2018-10-13 17:35:23 +08:00
parent ccf4fd02e3
commit 48b75e9ad6
8 changed files with 248 additions and 4 deletions

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,2 @@
services:
Rector\Rector\CodeQuality\SimplifyArraySearchRector: ~