Skip to content

Commit 6ba042e

Browse files
authored
[CodeQuality] Extract NullableObjectToInstanceofFactory shared by nullable-object instanceof rules (#8633)
1 parent 892d404 commit 6ba042e

5 files changed

Lines changed: 47 additions & 58 deletions

File tree

‎rules/CodeQuality/Rector/Identical/FlipTypeControlToUseExclusiveTypeRector.php‎

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@
88
use PhpParser\Node\Expr;
99
use PhpParser\Node\Expr\BinaryOp\Identical;
1010
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
11-
use PhpParser\Node\Expr\BooleanNot;
12-
use PhpParser\Node\Expr\Instanceof_;
13-
use PhpParser\Node\Name\FullyQualified;
1411
use PHPStan\Type\ObjectType;
12+
use Rector\PhpParser\Node\NullableObjectToInstanceofFactory;
1513
use Rector\PhpParser\Node\Value\ValueResolver;
1614
use Rector\Rector\AbstractRector;
1715
use Rector\RuleDoc\CodeSample\CodeSample;
1816
use Rector\RuleDoc\RuleDefinition;
19-
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
20-
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
2117
use Rector\TypeDeclaration\TypeAnalyzer\NullableTypeAnalyzer;
2218

2319
/**
@@ -28,6 +24,7 @@ final class FlipTypeControlToUseExclusiveTypeRector extends AbstractRector
2824
public function __construct(
2925
private readonly NullableTypeAnalyzer $nullableTypeAnalyzer,
3026
private readonly ValueResolver $valueResolver,
27+
private readonly NullableObjectToInstanceofFactory $nullableObjectToInstanceofFactory,
3128
) {
3229
}
3330

@@ -79,24 +76,7 @@ public function refactor(Node $node): ?Node
7976
return null;
8077
}
8178

82-
return $this->processConvertToExclusiveType($nullableObjectType, $expr, $node);
83-
}
84-
85-
private function processConvertToExclusiveType(
86-
ObjectType $objectType,
87-
Expr $expr,
88-
Identical|NotIdentical $binaryOp
89-
): BooleanNot|Instanceof_ {
90-
$fullyQualifiedType = $objectType instanceof ShortenedObjectType || $objectType instanceof AliasedObjectType
91-
? $objectType->getFullyQualifiedName()
92-
: $objectType->getClassName();
93-
94-
$instanceof = new Instanceof_($expr, new FullyQualified($fullyQualifiedType));
95-
if ($binaryOp instanceof NotIdentical) {
96-
return $instanceof;
97-
}
98-
99-
return new BooleanNot($instanceof);
79+
return $this->nullableObjectToInstanceofFactory->create($expr, $nullableObjectType, $node instanceof Identical);
10080
}
10181

10282
private function matchNullComparedExpr(Identical|NotIdentical $binaryOp): ?Expr

‎rules/CodeQuality/Rector/If_/ObjectExplicitBoolCompareRector.php‎

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
namespace Rector\CodeQuality\Rector\If_;
66

77
use PhpParser\Node;
8-
use PhpParser\Node\Expr;
9-
use PhpParser\Node\Expr\BooleanNot;
10-
use PhpParser\Node\Expr\Instanceof_;
118
use PhpParser\Node\Expr\Ternary;
12-
use PhpParser\Node\Name\FullyQualified;
139
use PhpParser\Node\Stmt\ElseIf_;
1410
use PhpParser\Node\Stmt\If_;
1511
use PHPStan\Type\ObjectType;
1612
use Rector\CodeQuality\NodeAnalyzer\ExplicitBoolConditionResolver;
1713
use Rector\CodeQuality\ValueObject\ExplicitBoolCondition;
14+
use Rector\PhpParser\Node\NullableObjectToInstanceofFactory;
1815
use Rector\Rector\AbstractRector;
1916
use Rector\RuleDoc\CodeSample\CodeSample;
2017
use Rector\RuleDoc\RuleDefinition;
@@ -26,6 +23,7 @@ final class ObjectExplicitBoolCompareRector extends AbstractRector
2623
{
2724
public function __construct(
2825
private readonly ExplicitBoolConditionResolver $explicitBoolConditionResolver,
26+
private readonly NullableObjectToInstanceofFactory $nullableObjectToInstanceofFactory,
2927
) {
3028
}
3129

@@ -85,16 +83,12 @@ public function refactor(Node $node): ?Node
8583
return null;
8684
}
8785

88-
$node->cond = $this->resolveNullable($explicitBoolCondition->isNegated(), $expr, $objectType);
86+
$node->cond = $this->nullableObjectToInstanceofFactory->create(
87+
$expr,
88+
$objectType,
89+
$explicitBoolCondition->isNegated()
90+
);
8991

9092
return $node;
9193
}
92-
93-
private function resolveNullable(bool $isNegated, Expr $expr, ObjectType $objectType): BooleanNot|Instanceof_
94-
{
95-
$fullyQualified = new FullyQualified($objectType->getClassName());
96-
$instanceof = new Instanceof_($expr, $fullyQualified);
97-
98-
return $isNegated ? new BooleanNot($instanceof) : $instanceof;
99-
}
10094
}

‎rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php‎

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
use PhpParser\Node\Expr\Empty_;
1515
use PhpParser\Node\Expr\Instanceof_;
1616
use PhpParser\Node\Expr\Isset_;
17-
use PhpParser\Node\Name\FullyQualified;
1817
use PHPStan\Type\ObjectType;
18+
use Rector\PhpParser\Node\NullableObjectToInstanceofFactory;
1919
use Rector\Rector\AbstractRector;
2020
use Rector\RuleDoc\CodeSample\CodeSample;
2121
use Rector\RuleDoc\RuleDefinition;
@@ -28,6 +28,7 @@ final class BinaryOpNullableToInstanceofRector extends AbstractRector
2828
{
2929
public function __construct(
3030
private readonly NullableTypeAnalyzer $nullableTypeAnalyzer,
31+
private readonly NullableObjectToInstanceofFactory $nullableObjectToInstanceofFactory,
3132
) {
3233
}
3334

@@ -96,15 +97,15 @@ private function processNullableInstance(BooleanAnd|BooleanOr $node): null|Boole
9697

9798
$hasChanged = false;
9899
if ($nullableObjectType instanceof ObjectType) {
99-
$node->left = $this->createExprInstanceof($node->left, $nullableObjectType);
100+
$node->left = $this->nullableObjectToInstanceofFactory->create($node->left, $nullableObjectType, false);
100101

101102
$hasChanged = true;
102103
}
103104

104105
$nullableObjectType = $this->resolveNullableObjectType($node->right);
105106

106107
if ($nullableObjectType instanceof ObjectType) {
107-
$node->right = $this->createExprInstanceof($node->right, $nullableObjectType);
108+
$node->right = $this->nullableObjectToInstanceofFactory->create($node->right, $nullableObjectType, false);
108109

109110
$hasChanged = true;
110111
}
@@ -123,7 +124,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr
123124
$nullableObjectType = $this->resolveNullableObjectType($booleanOr->left->expr);
124125

125126
if ($nullableObjectType instanceof ObjectType) {
126-
$booleanOr->left->expr = $this->createExprInstanceof($booleanOr->left->expr, $nullableObjectType);
127+
$booleanOr->left->expr = $this->nullableObjectToInstanceofFactory->create($booleanOr->left->expr, $nullableObjectType, false);
127128
$hasChanged = true;
128129
}
129130
}
@@ -132,7 +133,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr
132133
$nullableObjectType = $this->resolveNullableObjectType($booleanOr->right->expr);
133134

134135
if ($nullableObjectType instanceof ObjectType) {
135-
$booleanOr->right->expr = $this->createExprInstanceof($booleanOr->right->expr, $nullableObjectType);
136+
$booleanOr->right->expr = $this->nullableObjectToInstanceofFactory->create($booleanOr->right->expr, $nullableObjectType, false);
136137

137138
$hasChanged = true;
138139
}
@@ -164,10 +165,4 @@ private function isNeverNullableObject(Expr $expr): bool
164165
|| $expr instanceof Empty_
165166
|| $expr instanceof Isset_;
166167
}
167-
168-
private function createExprInstanceof(Expr $expr, ObjectType $objectType): Instanceof_
169-
{
170-
$fullyQualified = new FullyQualified($objectType->getClassName());
171-
return new Instanceof_($expr, $fullyQualified);
172-
}
173168
}

‎rules/TypeDeclaration/Rector/While_/WhileNullableToInstanceofRector.php‎

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@
55
namespace Rector\TypeDeclaration\Rector\While_;
66

77
use PhpParser\Node;
8-
use PhpParser\Node\Expr;
98
use PhpParser\Node\Expr\Assign;
109
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
11-
use PhpParser\Node\Expr\Instanceof_;
12-
use PhpParser\Node\Name\FullyQualified;
1310
use PhpParser\Node\Stmt\Do_;
1411
use PhpParser\Node\Stmt\While_;
1512
use PHPStan\Type\ObjectType;
1613
use PHPStan\Type\Type;
14+
use Rector\PhpParser\Node\NullableObjectToInstanceofFactory;
1715
use Rector\PhpParser\Node\Value\ValueResolver;
1816
use Rector\Rector\AbstractRector;
1917
use Rector\RuleDoc\CodeSample\CodeSample;
@@ -28,6 +26,7 @@ final class WhileNullableToInstanceofRector extends AbstractRector
2826
public function __construct(
2927
private readonly NullableTypeAnalyzer $nullableTypeAnalyzer,
3028
private readonly ValueResolver $valueResolver,
29+
private readonly NullableObjectToInstanceofFactory $nullableObjectToInstanceofFactory,
3130
) {
3231
}
3332

@@ -88,17 +87,11 @@ public function refactor(Node $node): ?Node
8887
return null;
8988
}
9089

91-
$node->cond = $this->createInstanceof($node->cond, $condNullableObjectType);
90+
$node->cond = $this->nullableObjectToInstanceofFactory->create($node->cond, $condNullableObjectType, false);
9291

9392
return $node;
9493
}
9594

96-
private function createInstanceof(Expr $expr, ObjectType $objectType): Instanceof_
97-
{
98-
$fullyQualified = new FullyQualified($objectType->getClassName());
99-
return new Instanceof_($expr, $fullyQualified);
100-
}
101-
10295
/**
10396
* @template TLoop of While_|Do_
10497
* @param TLoop $while
@@ -115,7 +108,7 @@ private function refactorNotIdentical(While_|Do_ $while, NotIdentical $notIdenti
115108
return null;
116109
}
117110

118-
$while->cond = $this->createInstanceof($notIdentical->left, $condNullableObjectType);
111+
$while->cond = $this->nullableObjectToInstanceofFactory->create($notIdentical->left, $condNullableObjectType, false);
119112
return $while;
120113
}
121114
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\PhpParser\Node;
6+
7+
use PhpParser\Node\Expr;
8+
use PhpParser\Node\Expr\BooleanNot;
9+
use PhpParser\Node\Expr\Instanceof_;
10+
use PhpParser\Node\Name\FullyQualified;
11+
use PHPStan\Type\ObjectType;
12+
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
13+
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
14+
15+
final class NullableObjectToInstanceofFactory
16+
{
17+
public function create(Expr $expr, ObjectType $objectType, bool $isNegated): BooleanNot|Instanceof_
18+
{
19+
$className = $objectType instanceof ShortenedObjectType || $objectType instanceof AliasedObjectType
20+
? $objectType->getFullyQualifiedName()
21+
: $objectType->getClassName();
22+
23+
$instanceof = new Instanceof_($expr, new FullyQualified($className));
24+
25+
return $isNegated ? new BooleanNot($instanceof) : $instanceof;
26+
}
27+
}

0 commit comments

Comments
 (0)