Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@
"Rector\\TypeDeclaration\\": "packages/TypeDeclaration/src",
"Rector\\ZendToSymfony\\": "packages/ZendToSymfony/src",
"Rector\\Utils\\DocumentationGenerator\\": "utils/DocumentationGenerator/src",
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src"
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src",
"Rector\\StrictCodeQuality\\": "packages/StrictCodeQuality/src"
}
},
"autoload-dev": {
Expand Down Expand Up @@ -151,7 +152,8 @@
"Rector\\Symfony\\Tests\\": "packages/Symfony/tests",
"Rector\\Twig\\Tests\\": "packages/Twig/tests",
"Rector\\TypeDeclaration\\Tests\\": "packages/TypeDeclaration/tests",
"Rector\\ZendToSymfony\\Tests\\": "packages/ZendToSymfony/tests"
"Rector\\ZendToSymfony\\Tests\\": "packages/ZendToSymfony/tests",
"Rector\\StrictCodeQuality\\Tests\\": "packages/StrictCodeQuality/tests"
},
"classmap": [
"packages/Symfony/tests/Rector/FrameworkBundle/AbstractToConstructorInjectionRectorSource",
Expand Down Expand Up @@ -209,4 +211,4 @@
"dev-master": "0.6-dev"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class FunctionCallToConstantRector extends AbstractRector
/**
* @var string[]string
*/
private $functionsToConstants;
private $functionsToConstants = [];

/**
* @param string[] $functionsToConstants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,17 @@ public function getNodeTypes(): array
*/
public function refactor(Node $node): ?Node
{
if (!$this->isName($node, 'version_compare')) {
if (! $this->isName($node, 'version_compare')) {
return null;
}

if (count($node->args) !== 3) {
return null;
}

if (!$this->isPhpVersionConstant($node->args[0]->value) && !$this->isPhpVersionConstant($node->args[1]->value)) {
if (! $this->isPhpVersionConstant($node->args[0]->value) && ! $this->isPhpVersionConstant(
$node->args[1]->value
)) {
return null;
}

Expand All @@ -107,35 +109,35 @@ public function refactor(Node $node): ?Node
return new $comparison($left, $right);
}

private function isPhpVersionConstant(Expr $value): bool
private function isPhpVersionConstant(Expr $expr): bool
{
if ($value instanceof ConstFetch && $value->name->toString() === 'PHP_VERSION') {
if ($expr instanceof ConstFetch && $expr->name->toString() === 'PHP_VERSION') {
return true;
}

return false;
}

private function getNewNodeForArg(Expr $value): Node
private function getNewNodeForArg(Expr $expr): Node
{
if ($this->isPhpVersionConstant($value)) {
if ($this->isPhpVersionConstant($expr)) {
return new ConstFetch(new Name('PHP_VERSION_ID'));
}

return $this->getVersionNumberFormVersionString($value);
return $this->getVersionNumberFormVersionString($expr);
}

private function getVersionNumberFormVersionString(Expr $value): LNumber
private function getVersionNumberFormVersionString(Expr $expr): LNumber
{
if (! $value instanceof String_) {
if (! $expr instanceof String_) {
throw new ShouldNotHappenException();
}

if (! preg_match('/^\d+\.\d+\.\d+$/', $value->value)) {
if (! preg_match('#^\d+\.\d+\.\d+$#', $expr->value)) {
throw new ShouldNotHappenException();
}

$versionParts = explode('.', $value->value);
$versionParts = explode('.', $expr->value);

return new LNumber((int) $versionParts[0] * 10000 + (int) $versionParts[1] * 100 + (int) $versionParts[2]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
namespace Rector\CodingStyle\Tests\Rector\FuncCall\FunctionCallToConstantRector;

use Iterator;
use Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\CodingStyle\Rector\FuncCall\FunctionCallToConstantRector;
use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class FunctionCallToConstantRectorTest extends AbstractRectorTestCase
Expand All @@ -22,7 +19,6 @@ public function test(string $file): void
public function provideDataForTest(): Iterator
{
yield [__DIR__ . '/Fixture/fixture.php.inc'];

}

protected function getRectorsWithConfiguration(): array
Expand All @@ -31,7 +27,7 @@ protected function getRectorsWithConfiguration(): array
FunctionCallToConstantRector::class => [
'$functionsToConstants' => [
'php_sapi_name' => 'PHP_SAPI',
'pi' => 'M_PI'
'pi' => 'M_PI',
],
],
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
namespace Rector\CodingStyle\Tests\Rector\FuncCall\VersionCompareFuncCallToConstantRector;

use Iterator;
use Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

Expand All @@ -22,7 +20,6 @@ public function provideDataForTest(): Iterator
{
yield [__DIR__ . '/Fixture/version-compare.php.inc'];
yield [__DIR__ . '/Fixture/skip-version-compare.php.inc'];

}

protected function getRectorClass(): string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php declare(strict_types=1);

namespace Rector\StrictCodeQuality\Rector\Stmt;

use PhpParser\Node;
use PhpParser\Node\Expr\Instanceof_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\Type\BooleanType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;

/**
* @see \Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\VarInlineAnnotationToAssertRectorTest
*/
final class VarInlineAnnotationToAssertRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Turn @var inline checks above code to assert() of hte type', [
new CodeSample(
<<<'PHP'
class SomeClass
{
public function run()
{
/** @var SpecificClass $value */
$value->call();
}
}
PHP
,
<<<'PHP'
class SomeClass
{
public function run()
{
/** @var SpecificClass $value */
assert($value instanceof SpecificClass);
$value->call();
}
}
PHP
),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Stmt::class];
}

/**
* @param Stmt $node
*/
public function refactor(Node $node): ?Node
{
$phpDocInfo = $this->getPhpDocInfo($node);
if ($phpDocInfo === null) {
return null;
}

$variable = $this->betterNodeFinder->findFirstInstanceOf($node, Variable::class);
if (! $variable instanceof Variable) {
return null;
}

$variable->setAttribute('comments', []);
$type = $phpDocInfo->getVarType();

$assertFuncCall = null;
if ($type instanceof ObjectType) {
$instanceOf = new Instanceof_($variable, new FullyQualified($type->getClassName()));
$assertFuncCall = $this->createFunction('assert', [$instanceOf]);
}

if ($type instanceof IntegerType) {
$isInt = $this->createFunction('is_int', [$variable]);
$assertFuncCall = $this->createFunction('assert', [$isInt]);
}

if ($type instanceof StringType) {
$isInt = $this->createFunction('is_string', [$variable]);
$assertFuncCall = $this->createFunction('assert', [$isInt]);
}

if ($type instanceof BooleanType) {
$isInt = $this->createFunction('is_bool', [$variable]);
$assertFuncCall = $this->createFunction('assert', [$isInt]);
}

if ($assertFuncCall === null) {
return null;
}

$this->addNodeBeforeNode($assertFuncCall, $node);

// cleanup @var annotation
$varTagValueNode = $phpDocInfo->getByType(VarTagValueNode::class);
$phpDocInfo->removeTagValueNodeFromNode($varTagValueNode);

$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $phpDocInfo);

return $node;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;

class SomeClass
{
public function run($value)
{
/** @var SpecificClass $value */
$value->call();
}
}

class SpecificClass
{
}

?>
-----
<?php

namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;

class SomeClass
{
public function run($value)
{
assert($value instanceof \Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture\SpecificClass);
$value->call();
}
}

class SpecificClass
{
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;

class ScalarClass
{
public function run($value)
{
/** @var int $value */
$value->call();

/** @var string $value */
$value->call();

/** @var bool $value */
$value->call();
}
}

?>
-----
<?php

namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;

class ScalarClass
{
public function run($value)
{
assert(is_int($value));
$value->call();
assert(is_string($value));

$value->call();
assert(is_bool($value));

$value->call();
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);

namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector;

use Iterator;
use Rector\StrictCodeQuality\Rector\Stmt\VarInlineAnnotationToAssertRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class VarInlineAnnotationToAssertRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}

public function provideDataForTest(): Iterator
{
yield [__DIR__ . '/Fixture/fixture.php.inc'];
yield [__DIR__ . '/Fixture/scalar.php.inc'];
}

protected function getRectorClass(): string
{
return VarInlineAnnotationToAssertRector::class;
}
}
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,5 @@ parameters:

- '#Method Rector\\BetterPhpDocParser\\PhpDocNodeFactory\\JMS\\SerializerTypePhpDocNodeFactory\:\:resolveTypeAnnotation\(\) should return JMS\\Serializer\\Annotation\\Type\|null but returns object\|null#'
- '#Method Rector\\BetterPhpDocParser\\PhpDocNodeFactory\\JMS\\SerializerTypePhpDocNodeFactory\:\:resolveTypeAnnotation\(\) should return JMS\\Serializer\\Annotation\\Type\|null but returns Doctrine\\ORM\\Mapping\\Annotation\|Symfony\\Component\\Validator\\Constraint\|null#'

- '#Parameter \#1 \$phpDocTagValueNode of method Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\:\:removeTagValueNodeFromNode\(\) expects PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode, PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode\|null given#'