mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 21:38:22 +01:00
Merge pull request #729 from rectorphp/simplify-empty-array-check
[WIP][CodeQuality] Create SimplifyEmptyArrayCheckRector
This commit is contained in:
commit
c2ccef23ab
@ -146,6 +146,17 @@ Simplify `in_array` and `array_keys` functions combination into `array_key_exist
|
||||
+array_key_exists("key", $array);
|
||||
```
|
||||
|
||||
### `SimplifyEmptyArrayCheckRector`
|
||||
|
||||
- class: `Rector\CodeQuality\Rector\FuncCall\SimplifyEmptyArrayCheckRector`
|
||||
|
||||
Simplify `is_array` and `empty` functions combination into a simple identical check for an empty array
|
||||
|
||||
```diff
|
||||
-is_array($values) && empty($values)
|
||||
+$values === []
|
||||
```
|
||||
|
||||
### `SimplifyStrposLowerRector`
|
||||
|
||||
- class: `Rector\CodeQuality\Rector\FuncCall\SimplifyStrposLowerRector`
|
||||
|
@ -0,0 +1,88 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Rector\FuncCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use PhpParser\Node\Expr\Empty_;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
final class SimplifyEmptyArrayCheckRector extends AbstractRector
|
||||
{
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition(
|
||||
'Simplify `is_array` and `empty` functions combination into a simple identical check for an empty array',
|
||||
[new CodeSample('is_array($values) && empty($values)', '$values === []')]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [BooleanAnd::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BooleanAnd $booleanAndNode
|
||||
*/
|
||||
public function refactor(Node $booleanAndNode): ?Node
|
||||
{
|
||||
$leftValue = $booleanAndNode->left;
|
||||
$rightValue = $booleanAndNode->right;
|
||||
if (! $this->isPreferableCheck($leftValue, $rightValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $rightValue instanceof BooleanNot && ! $leftValue instanceof BooleanNot) {
|
||||
/** @var FuncCall $variable */
|
||||
$variable = $leftValue instanceof Empty_ ? $leftValue->expr : $rightValue->expr;
|
||||
|
||||
return new Identical($variable, new Array_());
|
||||
}
|
||||
|
||||
$booleanNotExpr = $rightValue instanceof BooleanNot ? $rightValue->expr : $leftValue->expr;
|
||||
if (! $this->isName($booleanNotExpr, 'is_array') && ! $booleanNotExpr instanceof Empty_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$variable = $booleanNotExpr->expr ?? $booleanNotExpr;
|
||||
|
||||
return new NotIdentical($variable, new Array_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $node
|
||||
*/
|
||||
public function isNoneOfPreferableNodes($node): bool
|
||||
{
|
||||
return ! $this->isName($node, 'is_array') && ! $node instanceof Empty_ && ! $node instanceof BooleanNot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $leftValue
|
||||
* @param mixed $rightValue
|
||||
*/
|
||||
private function isPreferableCheck($leftValue, $rightValue): bool
|
||||
{
|
||||
if ($this->isNoneOfPreferableNodes($leftValue) || $this->isNoneOfPreferableNodes($rightValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// special case
|
||||
if ($leftValue instanceof BooleanNot && $rightValue instanceof BooleanNot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
final class MyClass
|
||||
{
|
||||
public function isEmptyArray($values): bool
|
||||
{
|
||||
return $values === [];
|
||||
}
|
||||
|
||||
public function isEmptyArray2($values): bool
|
||||
{
|
||||
return $values === [];
|
||||
}
|
||||
|
||||
public function isntEmptyArray($values): bool
|
||||
{
|
||||
return $values !== [];
|
||||
}
|
||||
|
||||
public function isntEmptyArray2($values): bool
|
||||
{
|
||||
return $values !== [];
|
||||
}
|
||||
|
||||
public function twoNegatives($values): bool
|
||||
{
|
||||
return ! empty($values->foo) && ! is_array($values->bar);
|
||||
}
|
||||
|
||||
public function functionCallInsideEmpty($values): bool
|
||||
{
|
||||
return array_filter($values) === [];
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
$invalid = is_array($var) && in_array('foo', $var);
|
||||
$almostValid = is_array($var) && count($var) > 0;
|
||||
$invalid2 = isset($this->events[$event]) && ! empty($this->events[$event]);
|
||||
$completelyInvalid = ! $value instanceof Foo && ! $value instanceof Bar;
|
@ -0,0 +1,31 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\FuncCall\SimplifyEmptyArrayCheckRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
/**
|
||||
* @covers \Rector\CodeQuality\Rector\FuncCall\SimplifyEmptyArrayCheckRector
|
||||
*/
|
||||
final class SimplifyEmptyArrayCheckRectorTest 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'];
|
||||
yield [__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc'];
|
||||
}
|
||||
|
||||
protected function provideConfig(): string
|
||||
{
|
||||
return __DIR__ . '/config.yml';
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
final class MyClass
|
||||
{
|
||||
public function isEmptyArray($values): bool
|
||||
{
|
||||
return is_array($values) && empty($values);
|
||||
}
|
||||
|
||||
public function isEmptyArray2($values): bool
|
||||
{
|
||||
return empty($values) && is_array($values);
|
||||
}
|
||||
|
||||
public function isntEmptyArray($values): bool
|
||||
{
|
||||
return is_array($values) && ! empty($values);
|
||||
}
|
||||
|
||||
public function isntEmptyArray2($values): bool
|
||||
{
|
||||
return ! empty($values) && is_array($values);
|
||||
}
|
||||
|
||||
public function twoNegatives($values): bool
|
||||
{
|
||||
return ! empty($values->foo) && ! is_array($values->bar);
|
||||
}
|
||||
|
||||
public function functionCallInsideEmpty($values): bool
|
||||
{
|
||||
return is_array($values) && empty(array_filter($values));
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
$invalid = is_array($var) && in_array('foo', $var);
|
||||
$almostValid = is_array($var) && count($var) > 0;
|
||||
$invalid2 = isset($this->events[$event]) && ! empty($this->events[$event]);
|
||||
$completelyInvalid = ! $value instanceof Foo && ! $value instanceof Bar;
|
@ -0,0 +1,2 @@
|
||||
services:
|
||||
Rector\CodeQuality\Rector\FuncCall\SimplifyEmptyArrayCheckRector: ~
|
Loading…
x
Reference in New Issue
Block a user