From e25df78489cf7cebb2a36192d7f1d62c5c102ed0 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 29 Jan 2023 12:39:10 +0000 Subject: [PATCH] Updated Rector to commit bbc100ce821ca98123ac0996673dbf48fc2b71e8 https://github.com/rectorphp/rector-src/commit/bbc100ce821ca98123ac0996673dbf48fc2b71e8 [TypeDeclaration] Add ReturnTypeFromStrictTernaryRector (#3318) --- config/set/type-declaration.php | 3 +- docs/rector_rules_overview.md | 23 ++- .../ReturnTypeFromStrictTernaryRector.php | 155 ++++++++++++++++++ .../ValueObject/TernaryIfElseTypes.php | 32 ++++ src/Application/VersionResolver.php | 4 +- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 2 + vendor/composer/autoload_real.php | 10 +- vendor/composer/autoload_static.php | 10 +- 9 files changed, 226 insertions(+), 15 deletions(-) create mode 100644 rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php create mode 100644 rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php diff --git a/config/set/type-declaration.php b/config/set/type-declaration.php index b0ded43fb18..c2df1176c69 100644 --- a/config/set/type-declaration.php +++ b/config/set/type-declaration.php @@ -7,6 +7,7 @@ use Rector\CodeQuality\Rector\ClassMethod\ReturnTypeFromStrictScalarReturnExprRe use Rector\Config\RectorConfig; use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector; use Rector\TypeDeclaration\Rector\Class_\PropertyTypeFromStrictSetterGetterRector; +use Rector\TypeDeclaration\Rector\Class_\ReturnTypeFromStrictTernaryRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeBasedOnPHPUnitDataProviderRector; use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeFromPropertyTypeRector; @@ -37,5 +38,5 @@ use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictGetterMethodRe use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictSetUpRector; use Rector\TypeDeclaration\Rector\Property\VarAnnotationIncorrectNullableRector; return static function (RectorConfig $rectorConfig) : void { - $rectorConfig->rules([AddClosureReturnTypeRector::class, AddArrowFunctionReturnTypeRector::class, ParamTypeByMethodCallTypeRector::class, TypedPropertyFromAssignsRector::class, ReturnAnnotationIncorrectNullableRector::class, VarAnnotationIncorrectNullableRector::class, ParamAnnotationIncorrectNullableRector::class, AddReturnTypeDeclarationBasedOnParentClassMethodRector::class, ReturnTypeFromStrictTypedPropertyRector::class, TypedPropertyFromStrictConstructorRector::class, ParamTypeFromStrictTypedPropertyRector::class, AddVoidReturnTypeWhereNoReturnRector::class, ReturnTypeFromReturnNewRector::class, TypedPropertyFromStrictGetterMethodReturnTypeRector::class, AddMethodCallBasedStrictParamTypeRector::class, ArrayShapeFromConstantArrayReturnRector::class, ReturnTypeFromStrictBoolReturnExprRector::class, ReturnTypeFromStrictNativeCallRector::class, ReturnTypeFromStrictNewArrayRector::class, ReturnTypeFromStrictScalarReturnExprRector::class, TypedPropertyFromStrictSetUpRector::class, ParamTypeByParentCallTypeRector::class, AddParamTypeSplFixedArrayRector::class, AddParamTypeBasedOnPHPUnitDataProviderRector::class, AddParamTypeFromPropertyTypeRector::class, AddReturnTypeDeclarationFromYieldsRector::class, ReturnTypeFromReturnDirectArrayRector::class, ReturnTypeFromStrictConstantReturnRector::class, ReturnTypeFromStrictTypedCallRector::class, ReturnNeverTypeRector::class, EmptyOnNullableObjectToInstanceOfRector::class, PropertyTypeFromStrictSetterGetterRector::class]); + $rectorConfig->rules([AddClosureReturnTypeRector::class, AddArrowFunctionReturnTypeRector::class, ParamTypeByMethodCallTypeRector::class, TypedPropertyFromAssignsRector::class, ReturnAnnotationIncorrectNullableRector::class, VarAnnotationIncorrectNullableRector::class, ParamAnnotationIncorrectNullableRector::class, AddReturnTypeDeclarationBasedOnParentClassMethodRector::class, ReturnTypeFromStrictTypedPropertyRector::class, TypedPropertyFromStrictConstructorRector::class, ParamTypeFromStrictTypedPropertyRector::class, AddVoidReturnTypeWhereNoReturnRector::class, ReturnTypeFromReturnNewRector::class, TypedPropertyFromStrictGetterMethodReturnTypeRector::class, AddMethodCallBasedStrictParamTypeRector::class, ArrayShapeFromConstantArrayReturnRector::class, ReturnTypeFromStrictBoolReturnExprRector::class, ReturnTypeFromStrictNativeCallRector::class, ReturnTypeFromStrictNewArrayRector::class, ReturnTypeFromStrictScalarReturnExprRector::class, TypedPropertyFromStrictSetUpRector::class, ParamTypeByParentCallTypeRector::class, AddParamTypeSplFixedArrayRector::class, AddParamTypeBasedOnPHPUnitDataProviderRector::class, AddParamTypeFromPropertyTypeRector::class, AddReturnTypeDeclarationFromYieldsRector::class, ReturnTypeFromReturnDirectArrayRector::class, ReturnTypeFromStrictConstantReturnRector::class, ReturnTypeFromStrictTypedCallRector::class, ReturnNeverTypeRector::class, EmptyOnNullableObjectToInstanceOfRector::class, PropertyTypeFromStrictSetterGetterRector::class, ReturnTypeFromStrictTernaryRector::class]); }; diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index 3325db1d93c..17705b6d737 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -1,4 +1,4 @@ -# 421 Rules Overview +# 422 Rules Overview
@@ -64,7 +64,7 @@ - [Transform](#transform) (34) -- [TypeDeclaration](#typedeclaration) (40) +- [TypeDeclaration](#typedeclaration) (41) - [Visibility](#visibility) (3) @@ -9689,6 +9689,25 @@ Add strict return array type based on created empty array and returned
+### ReturnTypeFromStrictTernaryRector + +Add method return type based on strict ternary values + +- class: [`Rector\TypeDeclaration\Rector\Class_\ReturnTypeFromStrictTernaryRector`](../rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php) + +```diff + final class SomeClass + { +- public function getValue($number) ++ public function getValue($number): int + { + return $number ? 100 : 500; + } + } +``` + +
+ ### ReturnTypeFromStrictTypedCallRector Add return type from strict return type of call diff --git a/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php b/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php new file mode 100644 index 00000000000..6a80039ac1c --- /dev/null +++ b/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php @@ -0,0 +1,155 @@ +parentClassMethodTypeOverrideGuard = $parentClassMethodTypeOverrideGuard; + } + public function getRuleDefinition() : RuleDefinition + { + return new RuleDefinition('Add method return type based on strict ternary values', [new CodeSample(<<<'CODE_SAMPLE' +final class SomeClass +{ + public function getValue($number) + { + return $number ? 100 : 500; + } +} +CODE_SAMPLE +, <<<'CODE_SAMPLE' +final class SomeClass +{ + public function getValue($number): int + { + return $number ? 100 : 500; + } +} +CODE_SAMPLE +)]); + } + /** + * @return array> + */ + public function getNodeTypes() : array + { + return [Class_::class]; + } + /** + * @param Class_ $node + */ + public function refactor(Node $node) : ?Node + { + $hasChanged = \false; + foreach ($node->getMethods() as $classMethod) { + if ($classMethod->returnType instanceof Node) { + continue; + } + $onlyStmt = $classMethod->stmts[0] ?? null; + if (!$onlyStmt instanceof Return_) { + continue; + } + if (!$onlyStmt->expr instanceof Ternary) { + continue; + } + $ternary = $onlyStmt->expr; + // has scalar in if/else of ternary + $ternaryIfElseTypes = $this->matchScalarTernaryIfElseTypes($ternary); + if (!$ternaryIfElseTypes instanceof TernaryIfElseTypes) { + continue; + } + $ifType = $ternaryIfElseTypes->getFirstType(); + $elseType = $ternaryIfElseTypes->getSecondType(); + if (!$this->areTypesEqual($ifType, $elseType)) { + continue; + } + $returnTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($ifType, TypeKind::RETURN); + if ($this->parentClassMethodTypeOverrideGuard->shouldSkipReturnTypeChange($classMethod, $ifType)) { + continue; + } + if (!$returnTypeNode instanceof Node) { + continue; + } + $classMethod->returnType = $returnTypeNode; + $hasChanged = \true; + } + if ($hasChanged) { + return $node; + } + return null; + } + public function provideMinPhpVersion() : int + { + return PhpVersionFeature::SCALAR_TYPES; + } + private function isAlwaysScalarExpr(?Expr $expr) : bool + { + // check if Scalar node + if ($expr instanceof Scalar) { + return \true; + } + // check if constant + if ($expr instanceof ConstFetch) { + return \true; + } + // check if class constant + return $expr instanceof ClassConstFetch; + } + private function areTypesEqual(Type $firstType, Type $secondType) : bool + { + // this is needed to make comparison tolerant to constant values, e.g. 5 and 10 are same only then + if ($firstType instanceof ConstantType) { + $firstType = $firstType->generalize(GeneralizePrecision::lessSpecific()); + } + if ($secondType instanceof ConstantType) { + $secondType = $secondType->generalize(GeneralizePrecision::lessSpecific()); + } + return $firstType->equals($secondType); + } + private function matchScalarTernaryIfElseTypes(Ternary $ternary) : ?TernaryIfElseTypes + { + if (!$this->isAlwaysScalarExpr($ternary->if)) { + return null; + } + if (!$this->isAlwaysScalarExpr($ternary->else)) { + return null; + } + /** @var Node\Expr $if */ + $if = $ternary->if; + /** @var Node\Expr $else */ + $else = $ternary->else; + $ifType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($if); + $elseType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($else); + return new TernaryIfElseTypes($ifType, $elseType); + } +} diff --git a/rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php b/rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php new file mode 100644 index 00000000000..0d8c8b9135b --- /dev/null +++ b/rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php @@ -0,0 +1,32 @@ +firstType = $firstType; + $this->secondType = $secondType; + } + public function getFirstType() : Type + { + return $this->firstType; + } + public function getSecondType() : Type + { + return $this->secondType; + } +} diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 51c6c413338..991092cbeaf 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 = '3450bed50204db27ca622d2056a82580a59914fb'; + public const PACKAGE_VERSION = 'bbc100ce821ca98123ac0996673dbf48fc2b71e8'; /** * @api * @var string */ - public const RELEASE_DATE = '2023-01-29 12:24:32'; + public const RELEASE_DATE = '2023-01-29 12:33:59'; /** * @var int */ diff --git a/vendor/autoload.php b/vendor/autoload.php index 79d22603e14..2ed136403ee 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 ComposerAutoloaderInit237f60ed8c00a6a6ce0e2d6d91af6957::getLoader(); +return ComposerAutoloaderInitdbfcbece273e5de83f5ecd5e170d7d08::getLoader(); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 6e535924a7e..7e567e6fcdf 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2768,6 +2768,7 @@ return array( 'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedCallRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedCallRector.php', 'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedPropertyRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedPropertyRector.php', 'Rector\\TypeDeclaration\\Rector\\Class_\\PropertyTypeFromStrictSetterGetterRector' => $baseDir . '/rules/TypeDeclaration/Rector/Class_/PropertyTypeFromStrictSetterGetterRector.php', + 'Rector\\TypeDeclaration\\Rector\\Class_\\ReturnTypeFromStrictTernaryRector' => $baseDir . '/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php', 'Rector\\TypeDeclaration\\Rector\\Closure\\AddClosureReturnTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/Closure/AddClosureReturnTypeRector.php', 'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => $baseDir . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php', 'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddParamTypeSplFixedArrayRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddParamTypeSplFixedArrayRector.php', @@ -2803,6 +2804,7 @@ return array( 'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => $baseDir . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php', 'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => $baseDir . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php', 'Rector\\TypeDeclaration\\ValueObject\\ReturnFalseAndReturnOther' => $baseDir . '/rules/TypeDeclaration/ValueObject/ReturnFalseAndReturnOther.php', + 'Rector\\TypeDeclaration\\ValueObject\\TernaryIfElseTypes' => $baseDir . '/rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php', 'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => $vendorDir . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => $baseDir . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php', diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 70522354a9b..b518fa1d3d6 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit237f60ed8c00a6a6ce0e2d6d91af6957 +class ComposerAutoloaderInitdbfcbece273e5de83f5ecd5e170d7d08 { private static $loader; @@ -22,17 +22,17 @@ class ComposerAutoloaderInit237f60ed8c00a6a6ce0e2d6d91af6957 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit237f60ed8c00a6a6ce0e2d6d91af6957', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInitdbfcbece273e5de83f5ecd5e170d7d08', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInit237f60ed8c00a6a6ce0e2d6d91af6957', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInitdbfcbece273e5de83f5ecd5e170d7d08', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08::$files; $requireFile = 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 a42225173bd..ec597fdc5e9 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,7 +4,7 @@ namespace Composer\Autoload; -class ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957 +class ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08 { public static $files = array ( 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', @@ -3013,6 +3013,7 @@ class ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957 'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedCallRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedCallRector.php', 'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedPropertyRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedPropertyRector.php', 'Rector\\TypeDeclaration\\Rector\\Class_\\PropertyTypeFromStrictSetterGetterRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Class_/PropertyTypeFromStrictSetterGetterRector.php', + 'Rector\\TypeDeclaration\\Rector\\Class_\\ReturnTypeFromStrictTernaryRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.php', 'Rector\\TypeDeclaration\\Rector\\Closure\\AddClosureReturnTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Closure/AddClosureReturnTypeRector.php', 'Rector\\TypeDeclaration\\Rector\\Empty_\\EmptyOnNullableObjectToInstanceOfRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.php', 'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddParamTypeSplFixedArrayRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddParamTypeSplFixedArrayRector.php', @@ -3048,6 +3049,7 @@ class ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957 'Rector\\TypeDeclaration\\ValueObject\\AssignToVariable' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/AssignToVariable.php', 'Rector\\TypeDeclaration\\ValueObject\\NestedArrayType' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/NestedArrayType.php', 'Rector\\TypeDeclaration\\ValueObject\\ReturnFalseAndReturnOther' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/ReturnFalseAndReturnOther.php', + 'Rector\\TypeDeclaration\\ValueObject\\TernaryIfElseTypes' => __DIR__ . '/../..' . '/rules/TypeDeclaration/ValueObject/TernaryIfElseTypes.php', 'Rector\\ValueObject\\ClassMethodWillChangeReturnType' => __DIR__ . '/..' . '/rector/rector-downgrade-php/src/ValueObject/ClassMethodWillChangeReturnType.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodParamVendorLockResolver' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php', 'Rector\\VendorLocker\\NodeVendorLocker\\ClassMethodReturnTypeOverrideGuard' => __DIR__ . '/../..' . '/packages/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php', @@ -3080,9 +3082,9 @@ class ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957 public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInit237f60ed8c00a6a6ce0e2d6d91af6957::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitdbfcbece273e5de83f5ecd5e170d7d08::$classMap; }, null, ClassLoader::class); }