Updated Rector to commit f13207737e25fef30190c1746a314b7e1dec6eb2

f13207737e [CodingStyle] Add NullifyUnionNullableRector (#3231)
This commit is contained in:
Tomas Votruba 2022-12-21 11:07:20 +00:00
parent 705057ef68
commit f4f085ed27
8 changed files with 179 additions and 29 deletions

View File

@ -1,4 +1,4 @@
# 415 Rules Overview
# 416 Rules Overview
<br>
@ -8,7 +8,7 @@
- [CodeQuality](#codequality) (79)
- [CodingStyle](#codingstyle) (38)
- [CodingStyle](#codingstyle) (39)
- [Compatibility](#compatibility) (1)
@ -2182,6 +2182,23 @@ Changes negate of empty comparison of nullable value to explicit === or !== comp
<br>
### NullifyUnionNullableRector
Changes already typed Type|null to ?Type
- class: [`Rector\CodingStyle\Rector\Property\NullifyUnionNullableRector`](../rules/CodingStyle/Rector/Property/NullifyUnionNullableRector.php)
```diff
final class SomeClass
{
- private null|stdClass $property;
+ private ?stdClass $property;
}
```
<br>
### OrderAttributesRector
Order attributes by desired names

View File

@ -39,6 +39,8 @@ use Rector\PHPStanStaticTypeMapper\TypeAnalyzer\UnionTypeCommonTypeNarrower;
use Rector\PHPStanStaticTypeMapper\ValueObject\UnionTypeAnalysis;
use function RectorPrefix202212\Symfony\Component\String\b;
use RectorPrefix202212\Symfony\Contracts\Service\Attribute\Required;
use RectorPrefix202212\Webmozart\Assert\Assert;
use RectorPrefix202212\Webmozart\Assert\InvalidArgumentException;
/**
* @implements TypeMapperInterface<UnionType>
*/
@ -141,6 +143,35 @@ final class UnionTypeMapper implements TypeMapperInterface
}
return $this->mapNullabledType($nullabledType, $typeKind);
}
/**
* @return PhpParserUnionType|\PhpParser\Node\NullableType|null
*/
public function resolveTypeWithNullablePHPParserUnionType(PhpParserUnionType $phpParserUnionType)
{
if (\count($phpParserUnionType->types) === 2) {
$phpParserUnionType->types = \array_values($phpParserUnionType->types);
$firstType = $phpParserUnionType->types[0];
$secondType = $phpParserUnionType->types[1];
try {
Assert::isAnyOf($firstType, [Name::class, Identifier::class]);
Assert::isAnyOf($secondType, [Name::class, Identifier::class]);
} catch (InvalidArgumentException $exception) {
return $this->resolveUnionTypes($phpParserUnionType);
}
$firstTypeValue = $firstType->toString();
$secondTypeValue = $secondType->toString();
if ($firstTypeValue === $secondTypeValue) {
return $this->resolveUnionTypes($phpParserUnionType);
}
if ($firstTypeValue === 'null') {
return $this->resolveNullableType(new NullableType($secondType));
}
if ($secondTypeValue === 'null') {
return $this->resolveNullableType(new NullableType($firstType));
}
}
return $this->resolveUnionTypes($phpParserUnionType);
}
private function resolveNullableType(NullableType $nullableType) : ?NullableType
{
if (!$this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::NULLABLE_TYPE)) {
@ -196,22 +227,8 @@ final class UnionTypeMapper implements TypeMapperInterface
}
return new Name($type);
}
/**
* @return PhpParserUnionType|\PhpParser\Node\NullableType|null
*/
private function resolveTypeWithNullablePHPParserUnionType(PhpParserUnionType $phpParserUnionType)
private function resolveUnionTypes(PhpParserUnionType $phpParserUnionType) : ?PhpParserUnionType
{
if (\count($phpParserUnionType->types) === 2) {
$phpParserUnionType->types = \array_values($phpParserUnionType->types);
$firstType = $phpParserUnionType->types[0];
$secondType = $phpParserUnionType->types[1];
if ($firstType instanceof Name && $firstType->toString() === 'null' && !$secondType instanceof PHPParserNodeIntersectionType) {
return $this->resolveNullableType(new NullableType($secondType));
}
if ($secondType instanceof Name && $secondType->toString() === 'null' && !$firstType instanceof PHPParserNodeIntersectionType) {
return $this->resolveNullableType(new NullableType($firstType));
}
}
if (!$this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::UNION_TYPES)) {
return null;
}

View File

@ -0,0 +1,114 @@
<?php
declare (strict_types=1);
namespace Rector\CodingStyle\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\UnionType;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\PHPStanStaticTypeMapper\TypeMapper\UnionTypeMapper;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\CodingStyle\Rector\Property\NullifyUnionNullableRector\NullifyUnionNullableRectorTest
*/
final class NullifyUnionNullableRector extends AbstractRector implements MinPhpVersionInterface
{
/**
* @readonly
* @var \Rector\PHPStanStaticTypeMapper\TypeMapper\UnionTypeMapper
*/
private $unionTypeMapper;
public function __construct(UnionTypeMapper $unionTypeMapper)
{
$this->unionTypeMapper = $unionTypeMapper;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Changes already typed Type|null to ?Type', [new CodeSample(<<<'CODE_SAMPLE'
final class SomeClass
{
private null|stdClass $property;
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
final class SomeClass
{
private ?stdClass $property;
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Property::class, Param::class, ClassMethod::class, Closure::class, Function_::class, ArrowFunction::class];
}
/**
* @param Property|Param|ClassMethod|Closure|Function_|ArrowFunction $node
*/
public function refactor(Node $node) : ?Node
{
if ($node instanceof Property || $node instanceof Param) {
return $this->processNullablePropertyParamType($node);
}
return $this->processNullableFunctionLikeReturnType($node);
}
public function provideMinPhpVersion() : int
{
return PhpVersionFeature::UNION_TYPES;
}
private function resolveNullableType(?Node $node) : ?NullableType
{
if (!$node instanceof Node) {
return null;
}
if (!$node instanceof UnionType) {
return null;
}
$nullableType = $this->unionTypeMapper->resolveTypeWithNullablePHPParserUnionType($node);
if (!$nullableType instanceof NullableType) {
return null;
}
return $nullableType;
}
/**
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $node
* @return null|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Param
*/
private function processNullablePropertyParamType($node)
{
$nullableType = $this->resolveNullableType($node->type);
if (!$nullableType instanceof NullableType) {
return null;
}
$node->type = $nullableType;
return $node;
}
/**
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\ArrowFunction $functionLike
*/
private function processNullableFunctionLikeReturnType($functionLike) : ?FunctionLike
{
$nullableType = $this->resolveNullableType($functionLike->returnType);
if (!$nullableType instanceof NullableType) {
return null;
}
$functionLike->returnType = $nullableType;
return $functionLike;
}
}

View File

@ -17,12 +17,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = 'b1fff57b7bdd56bff43211412483d6c33880533b';
public const PACKAGE_VERSION = 'f13207737e25fef30190c1746a314b7e1dec6eb2';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2022-12-21 10:30:05';
public const RELEASE_DATE = '2022-12-21 12:02:22';
/**
* @var int
*/

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInite6a2fa32a1cc64a3fef0c04459b73d39::getLoader();
return ComposerAutoloaderInit857f6c6fc247aa34acd4c7e654127a54::getLoader();

View File

@ -1308,6 +1308,7 @@ return array(
'Rector\\CodingStyle\\Rector\\PostInc\\PostIncDecToPreIncDecRector' => $baseDir . '/rules/CodingStyle/Rector/PostInc/PostIncDecToPreIncDecRector.php',
'Rector\\CodingStyle\\Rector\\Property\\AddFalseDefaultToBoolPropertyRector' => $baseDir . '/rules/CodingStyle/Rector/Property/AddFalseDefaultToBoolPropertyRector.php',
'Rector\\CodingStyle\\Rector\\Property\\InlineSimplePropertyAnnotationRector' => $baseDir . '/rules/CodingStyle/Rector/Property/InlineSimplePropertyAnnotationRector.php',
'Rector\\CodingStyle\\Rector\\Property\\NullifyUnionNullableRector' => $baseDir . '/rules/CodingStyle/Rector/Property/NullifyUnionNullableRector.php',
'Rector\\CodingStyle\\Rector\\Property\\SplitGroupedPropertiesRector' => $baseDir . '/rules/CodingStyle/Rector/Property/SplitGroupedPropertiesRector.php',
'Rector\\CodingStyle\\Rector\\Stmt\\NewlineAfterStatementRector' => $baseDir . '/rules/CodingStyle/Rector/Stmt/NewlineAfterStatementRector.php',
'Rector\\CodingStyle\\Rector\\String_\\SymplifyQuoteEscapeRector' => $baseDir . '/rules/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInite6a2fa32a1cc64a3fef0c04459b73d39
class ComposerAutoloaderInit857f6c6fc247aa34acd4c7e654127a54
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInite6a2fa32a1cc64a3fef0c04459b73d39
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInite6a2fa32a1cc64a3fef0c04459b73d39', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit857f6c6fc247aa34acd4c7e654127a54', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInite6a2fa32a1cc64a3fef0c04459b73d39', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit857f6c6fc247aa34acd4c7e654127a54', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54::$files;
$requireFile = static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39
class ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -1553,6 +1553,7 @@ class ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39
'Rector\\CodingStyle\\Rector\\PostInc\\PostIncDecToPreIncDecRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/PostInc/PostIncDecToPreIncDecRector.php',
'Rector\\CodingStyle\\Rector\\Property\\AddFalseDefaultToBoolPropertyRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/Property/AddFalseDefaultToBoolPropertyRector.php',
'Rector\\CodingStyle\\Rector\\Property\\InlineSimplePropertyAnnotationRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/Property/InlineSimplePropertyAnnotationRector.php',
'Rector\\CodingStyle\\Rector\\Property\\NullifyUnionNullableRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/Property/NullifyUnionNullableRector.php',
'Rector\\CodingStyle\\Rector\\Property\\SplitGroupedPropertiesRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/Property/SplitGroupedPropertiesRector.php',
'Rector\\CodingStyle\\Rector\\Stmt\\NewlineAfterStatementRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/Stmt/NewlineAfterStatementRector.php',
'Rector\\CodingStyle\\Rector\\String_\\SymplifyQuoteEscapeRector' => __DIR__ . '/../..' . '/rules/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector.php',
@ -3059,9 +3060,9 @@ class ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInite6a2fa32a1cc64a3fef0c04459b73d39::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit857f6c6fc247aa34acd4c7e654127a54::$classMap;
}, null, ClassLoader::class);
}