mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 22:08:00 +01:00
Add DeMorgan simplify Rector + update create command process
This commit is contained in:
parent
0b5cf22d0b
commit
71ab6b5599
@ -1,6 +1,5 @@
|
||||
services:
|
||||
Rector\CodeQuality\Rector\Assign\CombinedAssignRector: ~
|
||||
# Rector\CodeQuality\Rector\BinaryOp\SimplifyDeMorganBinaryRector: ~
|
||||
Rector\CodeQuality\Rector\BooleanAnd\SimplifyEmptyArrayCheckRector: ~
|
||||
Rector\CodeQuality\Rector\Expression\SimplifyMirrorAssignRector: ~
|
||||
Rector\CodeQuality\Rector\Foreach_\ForeachToInArrayRector: ~
|
||||
@ -20,3 +19,4 @@ services:
|
||||
|
||||
Rector\Php\Rector\FuncCall\RemoveExtraParametersRector: ~
|
||||
Rector\CodeQuality\Rector\LogicalOr\LogicalOrToBooleanOrRector: ~
|
||||
Rector\CodeQuality\Rector\BinaryOp\SimplifyDeMorganBinaryRector: ~
|
||||
|
@ -1,10 +1,15 @@
|
||||
# run "bin/rector create" to create a new Rector + tests from this config
|
||||
package: "CodeQuality"
|
||||
name: "SimplifyMirrorAssignRector"
|
||||
node_types:
|
||||
- "Assign" # put main node first
|
||||
|
||||
description: "Removes unneeded $a = $a assigns"
|
||||
code_before: "$a = $a;"
|
||||
code_after: ""
|
||||
source: "" # e.g. link to RFC or headline in upgrade guide, 1 or more in the list
|
||||
code_before: |
|
||||
<?php
|
||||
$a = $a;
|
||||
code_after: |
|
||||
<?php
|
||||
source: # e.g. link to RFC or headline in upgrade guide, 1 or more in the list
|
||||
- ""
|
||||
level: "" # e.g. symfony30.yml, target config to append this rector to
|
||||
|
@ -0,0 +1,100 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Rector\BinaryOp;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use Rector\PhpParser\Node\AssignAndBinaryMap;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* @see https://robots.thoughtbot.com/clearer-conditionals-using-de-morgans-laws
|
||||
* @see https://stackoverflow.com/questions/20043664/de-morgans-law
|
||||
*/
|
||||
final class SimplifyDeMorganBinaryRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var AssignAndBinaryMap
|
||||
*/
|
||||
private $assignAndBinaryMap;
|
||||
|
||||
public function __construct(AssignAndBinaryMap $assignAndBinaryMap)
|
||||
{
|
||||
$this->assignAndBinaryMap = $assignAndBinaryMap;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Simplify negated conditions with de Morgan theorem', [
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
<?php
|
||||
|
||||
$a = 5;
|
||||
$b = 10;
|
||||
$result = !($a > 20 || $b <= 50);
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
<?php
|
||||
|
||||
$a = 5;
|
||||
$b = 10;
|
||||
$result = $a <= 20 && $b > 50;
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [BooleanNot::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BooleanNot $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $node->expr instanceof BinaryOp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// and is simpler to read → keep it
|
||||
if ($node->expr instanceof BooleanAnd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$inversedNode = $this->assignAndBinaryMap->getInversed($node->expr);
|
||||
if ($inversedNode === null && $node->expr instanceof BooleanOr) {
|
||||
$inversedNode = BooleanAnd::class;
|
||||
}
|
||||
|
||||
return new $inversedNode($this->inverseNode($node->expr->left), $this->inverseNode($node->expr->right));
|
||||
}
|
||||
|
||||
private function inverseNode(Expr $node): Node
|
||||
{
|
||||
if ($node instanceof BinaryOp) {
|
||||
$inversedBinaryOp = $this->assignAndBinaryMap->getInversed($node);
|
||||
if ($inversedBinaryOp) {
|
||||
return new $inversedBinaryOp($node->left, $node->right);
|
||||
}
|
||||
}
|
||||
|
||||
if ($node instanceof BooleanNot) {
|
||||
return $node->expr;
|
||||
}
|
||||
|
||||
return new BooleanNot($node);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
function deMorgan()
|
||||
{
|
||||
$a = 5;
|
||||
$b = 10;
|
||||
$result = !($a > 20 || $b <= 50);
|
||||
|
||||
$c = 1000;
|
||||
$d = !($a === null || $b < $c);
|
||||
$d = !($a === null && $b < $c);
|
||||
|
||||
$e = !(!$a || $b !== $c);
|
||||
$f = !($a > $b || $c <= $d);
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
function deMorgan()
|
||||
{
|
||||
$a = 5;
|
||||
$b = 10;
|
||||
$result = $a <= 20 && $b > 50;
|
||||
|
||||
$c = 1000;
|
||||
$d = $a !== null && $b >= $c;
|
||||
$d = !($a === null && $b < $c);
|
||||
|
||||
$e = $a && $b === $c;
|
||||
$f = $a <= $b && $c > $d;
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,19 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\CodeQuality\Tests\Rector\BinaryOp\SimplifyDeMorganBinaryRector;
|
||||
|
||||
use Rector\CodeQuality\Rector\BinaryOp\SimplifyDeMorganBinaryRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class SimplifyDeMorganBinaryRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles([__DIR__ . '/Fixture/fixture.php.inc']);
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return SimplifyDeMorganBinaryRector::class;
|
||||
}
|
||||
}
|
@ -9,20 +9,18 @@ final class SimplifyIfReturnBoolRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFiles(
|
||||
[
|
||||
__DIR__ . '/Fixture/fixture.php.inc',
|
||||
__DIR__ . '/Fixture/fixture2.php.inc',
|
||||
__DIR__ . '/Fixture/fixture3.php.inc',
|
||||
__DIR__ . '/Fixture/fixture4.php.inc',
|
||||
__DIR__ . '/Fixture/fixture5.php.inc',
|
||||
__DIR__ . '/Fixture/fixture6.php.inc',
|
||||
__DIR__ . '/Fixture/fixture7.php.inc',
|
||||
__DIR__ . '/Fixture/fixture8.php.inc',
|
||||
__DIR__ . '/Fixture/fixture9.php.inc',
|
||||
__DIR__ . '/Fixture/fixture10.php.inc',
|
||||
]
|
||||
);
|
||||
$this->doTestFiles([
|
||||
__DIR__ . '/Fixture/fixture.php.inc',
|
||||
__DIR__ . '/Fixture/fixture2.php.inc',
|
||||
__DIR__ . '/Fixture/fixture3.php.inc',
|
||||
__DIR__ . '/Fixture/fixture4.php.inc',
|
||||
__DIR__ . '/Fixture/fixture5.php.inc',
|
||||
__DIR__ . '/Fixture/fixture6.php.inc',
|
||||
__DIR__ . '/Fixture/fixture7.php.inc',
|
||||
__DIR__ . '/Fixture/fixture8.php.inc',
|
||||
__DIR__ . '/Fixture/fixture9.php.inc',
|
||||
__DIR__ . '/Fixture/fixture10.php.inc',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getRectorClass(): string
|
||||
|
Loading…
x
Reference in New Issue
Block a user