Add DeMorgan simplify Rector + update create command process

This commit is contained in:
Tomas Votruba 2018-12-08 23:21:42 +01:00
parent 0b5cf22d0b
commit 71ab6b5599
6 changed files with 175 additions and 18 deletions

View File

@ -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: ~

View File

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

View File

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

View File

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

View File

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

View File

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