[PHPStan] Add RecastingRemovalRector

This commit is contained in:
Tomas Votruba 2018-11-08 13:51:29 +01:00
parent 14d806990f
commit dabf8bac49
12 changed files with 176 additions and 2 deletions

View File

@ -50,6 +50,7 @@
"Rector\\Silverstripe\\": "packages/Silverstripe/src",
"Rector\\Sensio\\": "packages/Sensio/src",
"Rector\\Sylius\\": "packages/Sylius/src",
"Rector\\PHPStan\\": "packages/PHPStan/src",
"Rector\\PHPUnit\\": "packages/PHPUnit/src",
"Rector\\Twig\\": "packages/Twig/src",
"Rector\\PhpParser\\": "packages/PhpParser/src",
@ -73,6 +74,7 @@
"Rector\\Silverstripe\\Tests\\": "packages/Silverstripe/tests",
"Rector\\Sensio\\Tests\\": "packages/Sensio/tests",
"Rector\\Sylius\\Tests\\": "packages/Sylius/tests",
"Rector\\PHPStan\\Tests\\": "packages/PHPStan/tests",
"Rector\\PHPUnit\\Tests\\": "packages/PHPUnit/tests",
"Rector\\PhpParser\\Tests\\": "packages/PhpParser/tests",
"Rector\\Twig\\Tests\\": "packages/Twig/tests",

View File

@ -0,0 +1,2 @@
services:
Rector\PHPStan\Rector\Cast\RecastingRemovalRector: ~

View File

@ -4,6 +4,7 @@ namespace Rector\CodeQuality\Rector\Stmt;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
@ -35,7 +36,7 @@ CODE_SAMPLE
*/
public function getNodeTypes(): array
{
return [Variable::class, PropertyFetch::class, ArrayDimFetch::class];
return [Variable::class, PropertyFetch::class, ArrayDimFetch::class, Cast::class];
}
/**

View File

@ -3,3 +3,4 @@
$value = 5;
$value;
(float) $value;

View File

@ -128,7 +128,7 @@ final class ConfigurationFactory
$finder = Finder::create()->files()
->in($this->levelsDirectory)
->name(sprintf('#%s$#', $level));
->name(sprintf('#%s(\.yml)?$#', $level));
/** @var SplFileInfo[] $fileInfos */
$fileInfos = iterator_to_array($finder->getIterator());

View File

@ -0,0 +1,99 @@
<?php declare(strict_types=1);
namespace Rector\PHPStan\Rector\Cast;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Expr\Cast\Array_;
use PhpParser\Node\Expr\Cast\Bool_;
use PhpParser\Node\Expr\Cast\Double;
use PhpParser\Node\Expr\Cast\Int_;
use PhpParser\Node\Expr\Cast\Object_;
use PhpParser\Node\Expr\Cast\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\Node\Attribute;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
final class RecastingRemovalRector extends AbstractRector
{
/**
* @var string[]
*/
private $castClassToNodeType = [
String_::class => StringType::class,
Bool_::class => BooleanType::class,
Array_::class => ArrayType::class,
Int_::class => IntegerType::class,
Object_::class => ObjectType::class,
Double::class => FloatType::class,
];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Removes recasting of the same type', [
new CodeSample(
<<<'CODE_SAMPLE'
$string = '';
$string = (string) $string;
$array = [];
$array = (array) $array;
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$string = '';
$string = $string;
$array = [];
$array = $array;
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Cast::class];
}
/**
* @param Cast $node
*/
public function refactor(Node $node): ?Node
{
$nodeClass = get_class($node);
if (! isset($this->castClassToNodeType[$nodeClass])) {
return null;
}
$nodeType = $this->getNodeType($node->expr);
$sameNodeType = $this->castClassToNodeType[$nodeClass];
if (! is_a($nodeType, $sameNodeType, true)) {
return null;
}
return $node->expr;
}
private function getNodeType(Expr $node): Type
{
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(Attribute::SCOPE);
return $nodeScope->getType($node);
}
}

View File

@ -0,0 +1,9 @@
<?php
$string = '';
$string = $string;
$array = [];
$array = $array;
$array = (array) $string;

View File

@ -0,0 +1,9 @@
<?php
$object = new stdClass();
$object = $object;
$object = (array) $object;
$int = 5;
$float = (float) $int;
$int = $int;

View File

@ -0,0 +1,31 @@
<?php declare(strict_types=1);
namespace Rector\PHPStan\Tests\Rector\Cast\RecastingRemovalRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
/**
* @covers \Rector\PHPStan\Rector\Cast\RecastingRemovalRector
*/
final class RecastingRemovalRectorTest 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';
}
}

View File

@ -0,0 +1,9 @@
<?php
$string = '';
$string = (string) $string;
$array = [];
$array = (array) $array;
$array = (array) $string;

View File

@ -0,0 +1,9 @@
<?php
$object = new stdClass();
$object = (object) $object;
$object = (array) $object;
$int = 5;
$float = (float) $int;
$int = (int) $int;

View File

@ -0,0 +1,2 @@
services:
Rector\PHPStan\Rector\Cast\RecastingRemovalRector: ~