diff --git a/config/set/instanceof.php b/config/set/instanceof.php
index a417cf8bd67..969bf04fac0 100644
--- a/config/set/instanceof.php
+++ b/config/set/instanceof.php
@@ -9,8 +9,9 @@ use Rector\CodeQuality\Rector\Identical\GetClassToInstanceOfRector;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\BinaryOp\RemoveDuplicatedInstanceOfRector;
use Rector\DeadCode\Rector\If_\RemoveDeadInstanceOfRector;
+use Rector\TypeDeclaration\Rector\BooleanAnd\BinaryOpNullableToInstanceofRector;
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
use Rector\TypeDeclaration\Rector\Ternary\FlipNegatedTernaryInstanceofRector;
return static function (RectorConfig $rectorConfig) : void {
- $rectorConfig->rules([EmptyOnNullableObjectToInstanceOfRector::class, GetClassToInstanceOfRector::class, InlineIsAInstanceOfRector::class, FlipTypeControlToUseExclusiveTypeRector::class, RemoveDuplicatedInstanceOfRector::class, RemoveDeadInstanceOfRector::class, FlipNegatedTernaryInstanceofRector::class]);
+ $rectorConfig->rules([EmptyOnNullableObjectToInstanceOfRector::class, GetClassToInstanceOfRector::class, InlineIsAInstanceOfRector::class, FlipTypeControlToUseExclusiveTypeRector::class, RemoveDuplicatedInstanceOfRector::class, RemoveDeadInstanceOfRector::class, FlipNegatedTernaryInstanceofRector::class, BinaryOpNullableToInstanceofRector::class]);
};
diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md
index 9c849f075e0..afdfede8f06 100644
--- a/docs/rector_rules_overview.md
+++ b/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 418 Rules Overview
+# 419 Rules Overview
@@ -64,7 +64,7 @@
- [Transform](#transform) (34)
-- [TypeDeclaration](#typedeclaration) (38)
+- [TypeDeclaration](#typedeclaration) (39)
- [Visibility](#visibility) (3)
@@ -9533,6 +9533,26 @@ Add array shape exact types based on constant keys of array
+### BinaryOpNullableToInstanceofRector
+
+Change && and || between nullable objects to instanceof compares
+
+- class: [`Rector\TypeDeclaration\Rector\BooleanAnd\BinaryOpNullableToInstanceofRector`](../rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php)
+
+```diff
+ function someFunction(?SomeClass $someClass)
+ {
+- if ($someClass && $someClass->someMethod()) {
++ if ($someClass instanceof SomeClass && $someClass->someMethod()) {
+ return 'yes';
+ }
+
+ return 'no';
+ }
+```
+
+
+
### DeclareStrictTypesRector
Add declare(strict_types=1) if missing
diff --git a/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php b/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php
new file mode 100644
index 00000000000..7e98c4fbcc5
--- /dev/null
+++ b/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php
@@ -0,0 +1,84 @@
+someMethod()) {
+ return 'yes';
+ }
+
+ return 'no';
+}
+CODE_SAMPLE
+, <<<'CODE_SAMPLE'
+function someFunction(?SomeClass $someClass)
+{
+ if ($someClass instanceof SomeClass && $someClass->someMethod()) {
+ return 'yes';
+ }
+
+ return 'no';
+}
+CODE_SAMPLE
+)]);
+ }
+ /**
+ * @return array>
+ */
+ public function getNodeTypes() : array
+ {
+ return [BooleanAnd::class, BooleanOr::class];
+ }
+ /**
+ * @param BooleanAnd|BooleanOr $node
+ */
+ public function refactor(Node $node) : ?Node
+ {
+ $nullableObjectType = $this->returnNullableObjectType($node->left);
+ if ($nullableObjectType instanceof ObjectType) {
+ $node->left = $this->createExprInstanceof($node->left, $nullableObjectType);
+ return $node;
+ }
+ $nullableObjectType = $this->returnNullableObjectType($node->right);
+ if ($nullableObjectType instanceof ObjectType) {
+ $node->right = $this->createExprInstanceof($node->right, $nullableObjectType);
+ return $node;
+ }
+ return null;
+ }
+ private function returnNullableObjectType(Expr $expr) : ?\PHPStan\Type\ObjectType
+ {
+ $exprType = $this->getType($expr);
+ $baseType = TypeCombinator::removeNull($exprType);
+ if (!$baseType instanceof ObjectType) {
+ return null;
+ }
+ return $baseType;
+ }
+ private function createExprInstanceof(Expr $expr, ObjectType $objectType) : Instanceof_
+ {
+ $fullyQualified = new FullyQualified($objectType->getClassName());
+ return new Instanceof_($expr, $fullyQualified);
+ }
+}
diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php
index e0bb82e015c..e202cd75c5f 100644
--- a/src/Application/VersionResolver.php
+++ b/src/Application/VersionResolver.php
@@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
- public const PACKAGE_VERSION = 'e3e51469627756e976a8b8afb718d77caad3a0c4';
+ public const PACKAGE_VERSION = 'a4c1d7e481d426cb82d5a5bf89bfcac21deb3764';
/**
* @api
* @var string
*/
- public const RELEASE_DATE = '2023-04-19 09:10:36';
+ public const RELEASE_DATE = '2023-04-19 10:59:12';
/**
* @var int
*/
diff --git a/vendor/autoload.php b/vendor/autoload.php
index ff93aea0906..db7f9319d62 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInitbfb42ada5abb6e84d997dbeff733f1de::getLoader();
+return ComposerAutoloaderInitbafd83555148cc453afc1531baabf75a::getLoader();
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 07bc8917fa1..ceb2a16ac7d 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -2805,6 +2805,7 @@ return array(
'Rector\\TypeDeclaration\\PHPStan\\TypeSpecifier\\SelfStaticParentTypeSpecifier' => $baseDir . '/rules/TypeDeclaration/PHPStan/TypeSpecifier/SelfStaticParentTypeSpecifier.php',
'Rector\\TypeDeclaration\\PhpDocParser\\ParamPhpDocNodeFactory' => $baseDir . '/rules/TypeDeclaration/PhpDocParser/ParamPhpDocNodeFactory.php',
'Rector\\TypeDeclaration\\Rector\\ArrowFunction\\AddArrowFunctionReturnTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector.php',
+ 'Rector\\TypeDeclaration\\Rector\\BooleanAnd\\BinaryOpNullableToInstanceofRector' => $baseDir . '/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddMethodCallBasedStrictParamTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddParamTypeBasedOnPHPUnitDataProviderRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddParamTypeDeclarationRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeDeclarationRector.php',
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index ee23aaa7b3f..644bb0f85d0 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInitbfb42ada5abb6e84d997dbeff733f1de
+class ComposerAutoloaderInitbafd83555148cc453afc1531baabf75a
{
private static $loader;
@@ -22,17 +22,17 @@ class ComposerAutoloaderInitbfb42ada5abb6e84d997dbeff733f1de
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInitbfb42ada5abb6e84d997dbeff733f1de', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInitbafd83555148cc453afc1531baabf75a', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInitbfb42ada5abb6e84d997dbeff733f1de', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInitbafd83555148cc453afc1531baabf75a', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(\Composer\Autoload\ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de::getInitializer($loader));
+ call_user_func(\Composer\Autoload\ComposerStaticInitbafd83555148cc453afc1531baabf75a::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
- $filesToLoad = \Composer\Autoload\ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de::$files;
+ $filesToLoad = \Composer\Autoload\ComposerStaticInitbafd83555148cc453afc1531baabf75a::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index d16d823c382..cddf525231b 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace Composer\Autoload;
-class ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de
+class ComposerStaticInitbafd83555148cc453afc1531baabf75a
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@@ -3052,6 +3052,7 @@ class ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de
'Rector\\TypeDeclaration\\PHPStan\\TypeSpecifier\\SelfStaticParentTypeSpecifier' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PHPStan/TypeSpecifier/SelfStaticParentTypeSpecifier.php',
'Rector\\TypeDeclaration\\PhpDocParser\\ParamPhpDocNodeFactory' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PhpDocParser/ParamPhpDocNodeFactory.php',
'Rector\\TypeDeclaration\\Rector\\ArrowFunction\\AddArrowFunctionReturnTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector.php',
+ 'Rector\\TypeDeclaration\\Rector\\BooleanAnd\\BinaryOpNullableToInstanceofRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddMethodCallBasedStrictParamTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddParamTypeBasedOnPHPUnitDataProviderRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddParamTypeDeclarationRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeDeclarationRector.php',
@@ -3143,9 +3144,9 @@ class ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInitbfb42ada5abb6e84d997dbeff733f1de::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInitbafd83555148cc453afc1531baabf75a::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInitbafd83555148cc453afc1531baabf75a::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInitbafd83555148cc453afc1531baabf75a::$classMap;
}, null, ClassLoader::class);
}