[CodeQuality] Register IssetOnPropertyObjectToPropertyExistsRector to code-quality config set (#4441)

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Abdul Malik Ikhsan 2020-10-19 01:42:49 +07:00 committed by GitHub
parent e845d7cea8
commit 26ab509d7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 25 deletions

View File

@ -51,6 +51,7 @@ use Rector\CodeQuality\Rector\If_\SimplifyIfIssetToNullCoalescingRector;
use Rector\CodeQuality\Rector\If_\SimplifyIfNotNullReturnRector;
use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector;
use Rector\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector;
use Rector\CodeQuality\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector;
use Rector\CodeQuality\Rector\LogicalAnd\AndAssignsToSeparateLinesRector;
use Rector\CodeQuality\Rector\LogicalAnd\LogicalToBooleanRector;
use Rector\CodeQuality\Rector\Name\FixClassCaseSensitivityNameRector;
@ -219,4 +220,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(VarToPublicPropertyRector::class);
$services->set(FixClassCaseSensitivityNameRector::class);
$services->set(IssetOnPropertyObjectToPropertyExistsRector::class);
};

View File

@ -139,7 +139,7 @@ CODE_SAMPLE
private function shouldSkipForeach(Foreach_ $foreach): bool
{
if (isset($foreach->keyVar)) {
if ($foreach->keyVar !== null) {
return true;
}

View File

@ -15,6 +15,9 @@ use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ThisType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -79,29 +82,61 @@ CODE_SAMPLE
}
$previous = $issetVar->getAttribute(AttributeKey::PREVIOUS_NODE);
$current = $issetVar->getAttribute(AttributeKey::PARENT_NODE);
$next = $issetVar->getAttribute(AttributeKey::NEXT_NODE);
if ($previous && $previous->getAttribute(AttributeKey::PARENT_NODE) === $current) {
continue;
}
if ($next && $next->getAttribute(AttributeKey::PARENT_NODE) === $current) {
if ($this->isFoundInPreviuosOrNext($previous, $next, $node)) {
continue;
}
/** @var Expr $object */
$object = $issetVar->var->getAttribute(AttributeKey::ORIGINAL_NODE);
/** @var Scope $scope */
$scope = $object->getAttribute(AttributeKey::SCOPE);
/** @var ThisType|ObjectType $type */
$type = $scope->getType($object);
if ($type instanceof ThisType) {
return new NotIdentical($issetVar, $this->createNull());
}
/** @var Identifier $name */
$name = $issetVar->name;
$property = $name->toString();
$args = [new Arg($object), new Arg(new String_($property))];
$propertyExistsFuncCall = new FuncCall(new Name('property_exists'), $args);
if ($type instanceof ObjectType) {
/** @var string $className */
$className = $type->getClassName();
return new BooleanAnd($propertyExistsFuncCall, new NotIdentical($issetVar, $this->createNull()));
$isPropertyAlwaysExists = property_exists($className, $property);
if ($isPropertyAlwaysExists) {
return new NotIdentical($issetVar, $this->createNull());
}
}
return $this->replaceToPropertyExistsWithNullCheck($object, $property, $issetVar);
}
return null;
}
/**
* @param Node $previous
* @param Node $next
*/
private function isFoundInPreviuosOrNext(?Node $previous = null, ?Node $next = null, Isset_ $isset): bool
{
if ($previous && $previous->getAttribute(AttributeKey::PARENT_NODE) === $isset) {
return true;
}
return $next && $next->getAttribute(AttributeKey::PARENT_NODE) === $isset;
}
private function replaceToPropertyExistsWithNullCheck(Expr $expr, string $property, Expr $issetVar): BooleanAnd
{
$args = [new Arg($expr), new Arg(new String_($property))];
$propertyExistsFuncCall = new FuncCall(new Name('property_exists'), $args);
return new BooleanAnd($propertyExistsFuncCall, new NotIdentical($issetVar, $this->createNull()));
}
}

View File

@ -28,9 +28,9 @@ class SomeClass
public function run()
{
property_exists($this, 'x') && $this->x !== null;
property_exists($this, 'y') && $this->y !== null;
property_exists($this, 'x') && $this->x !== null && (property_exists($this, 'y') && $this->y !== null);
$this->x !== null;
$this->y !== null;
$this->x !== null && $this->y !== null;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Rector\CodeQuality\Tests\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector\Fixture;
class SomeClass2
{
public $x;
public $y;
public function run()
{
$obj = new self();
isset($obj->x);
isset($obj->y);
isset($obj->x) && isset($obj->y);
}
}
?>
-----
<?php
namespace Rector\CodeQuality\Tests\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector\Fixture;
class SomeClass2
{
public $x;
public $y;
public function run()
{
$obj = new self();
$obj->x !== null;
$obj->y !== null;
$obj->x !== null && $obj->y !== null;
}
}
?>

View File

@ -2,14 +2,19 @@
namespace Rector\CodeQuality\Tests\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector\Fixture;
class SomeClass2
class SomeClass4
{
public $x;
public $y;
public function init()
{
$this->x = 'a';
$this->y = 'b';
}
public function run()
{
$obj = new self();
$obj->init();
isset($obj->x);
isset($obj->y);
isset($obj->x) && isset($obj->y);
@ -22,18 +27,23 @@ class SomeClass2
namespace Rector\CodeQuality\Tests\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector\Fixture;
class SomeClass2
class SomeClass4
{
public $x;
public $y;
public function init()
{
$this->x = 'a';
$this->y = 'b';
}
public function run()
{
$obj = new self();
$obj->init();
property_exists($obj, 'x') && $obj->x !== null;
property_exists($obj, 'y') && $obj->y !== null;
property_exists($obj, 'x') && $obj->x !== null && (property_exists($obj, 'y') && $obj->y !== null);
}
}
?>
?>

View File

@ -81,7 +81,7 @@ final class ServiceMapProvider
foreach ($xml->services->service as $def) {
/** @var SimpleXMLElement $attrs */
$attrs = $def->attributes();
if (! isset($attrs->id)) {
if (! (property_exists($attrs, 'id') && $attrs->id !== null)) {
continue;
}
@ -152,10 +152,10 @@ final class ServiceMapProvider
return new ServiceDefinition(
strpos((string) $attrs->id, '.') === 0 ? Strings::substring((string) $attrs->id, 1) : (string) $attrs->id,
isset($attrs->class) ? (string) $attrs->class : null,
! isset($attrs->public) || (string) $attrs->public !== 'false',
isset($attrs->synthetic) && (string) $attrs->synthetic === 'true',
isset($attrs->alias) ? (string) $attrs->alias : null,
property_exists($attrs, 'class') && $attrs->class !== null ? (string) $attrs->class : null,
! (property_exists($attrs, 'public') && $attrs->public !== null) || (string) $attrs->public !== 'false',
property_exists($attrs, 'synthetic') && $attrs->synthetic !== null && (string) $attrs->synthetic === 'true',
property_exists($attrs, 'alias') && $attrs->alias !== null ? (string) $attrs->alias : null,
$tags
);
}