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); }