Updated Rector to commit e0ba9a3527

e0ba9a3527 [DowngradePhp81] Handle New_ inside array on DowngradeNewInInitializerRector (#1508)
This commit is contained in:
Tomas Votruba 2021-12-15 19:55:35 +00:00
parent c079f6ad1a
commit fd80b6bdc2
23 changed files with 685 additions and 125 deletions

View File

@ -5,6 +5,7 @@ namespace Rector\DowngradePhp80\Rector\Class_;
use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
@ -178,7 +179,8 @@ CODE_SAMPLE
$property->flags = $param->flags;
$property->type = $param->type;
$this->decoratePropertyWithParamDocInfo($param, $property);
if ($param->default !== null) {
$hasNew = $param->default === null ? \false : (bool) $this->betterNodeFinder->findFirstInstanceOf($param->default, \PhpParser\Node\Expr\New_::class);
if ($param->default !== null && !$hasNew) {
$property->props[0]->default = $param->default;
}
$properties[] = $property;

View File

@ -5,6 +5,7 @@ namespace Rector\DowngradePhp81\Rector\FunctionLike;
use PhpParser\Node;
use PhpParser\Node\ComplexType;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\AssignOp\Coalesce as AssignCoalesce;
@ -17,6 +18,7 @@ use PhpParser\Node\Identifier;
use PhpParser\Node\IntersectionType;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
@ -87,10 +89,7 @@ CODE_SAMPLE
private function shouldSkip(\PhpParser\Node\FunctionLike $functionLike) : bool
{
foreach ($functionLike->getParams() as $param) {
if (!$param->default instanceof \PhpParser\Node\Expr\New_) {
continue;
}
if ($param->type instanceof \PhpParser\Node\IntersectionType) {
if ($this->isParamSkipped($param)) {
continue;
}
return \false;
@ -105,24 +104,37 @@ CODE_SAMPLE
$stmts = [new \PhpParser\Node\Stmt\Return_($functionLike->expr)];
return $this->anonymousFunctionFactory->create($functionLike->params, $stmts, $functionLike->returnType, $functionLike->static);
}
private function isParamSkipped(\PhpParser\Node\Param $param) : bool
{
if ($param->default === null) {
return \true;
}
$hasNew = (bool) $this->betterNodeFinder->findFirstInstanceOf($param->default, \PhpParser\Node\Expr\New_::class);
if (!$hasNew) {
return \true;
}
return $param->type instanceof \PhpParser\Node\IntersectionType;
}
private function replaceNewInParams(\PhpParser\Node\FunctionLike $functionLike) : \PhpParser\Node\FunctionLike
{
$isConstructor = $functionLike instanceof \PhpParser\Node\Stmt\ClassMethod && $this->isName($functionLike, \Rector\Core\ValueObject\MethodName::CONSTRUCT);
$stmts = [];
foreach ($functionLike->getParams() as $param) {
if (!$param->default instanceof \PhpParser\Node\Expr\New_) {
if ($this->isParamSkipped($param)) {
continue;
}
/** @var Expr $default */
$default = $param->default;
// check for property promotion
if ($isConstructor && $param->flags > 0) {
$propertyFetch = new \PhpParser\Node\Expr\PropertyFetch(new \PhpParser\Node\Expr\Variable('this'), $param->var->name);
$coalesce = new \PhpParser\Node\Expr\BinaryOp\Coalesce($param->var, $param->default);
$coalesce = new \PhpParser\Node\Expr\BinaryOp\Coalesce($param->var, $default);
$assign = new \PhpParser\Node\Expr\Assign($propertyFetch, $coalesce);
if ($param->type !== null) {
$param->type = $this->ensureNullableType($param->type);
}
} else {
$assign = new \PhpParser\Node\Expr\AssignOp\Coalesce($param->var, $param->default);
$assign = new \PhpParser\Node\Expr\AssignOp\Coalesce($param->var, $default);
}
$stmts[] = new \PhpParser\Node\Stmt\Expression($assign);
$param->default = $this->nodeFactory->createNull();

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = '00b9f8faa2ef8e215cfbf5c6eea784ae4899d400';
public const PACKAGE_VERSION = 'e0ba9a3527cfe7197e33904db61e1f8703b68cc5';
/**
* @var string
*/
public const RELEASE_DATE = '2021-12-15 16:49:02';
public const RELEASE_DATE = '2021-12-15 19:37:50';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20211215\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061::getLoader();
return ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c::getLoader();

View File

@ -1893,12 +1893,16 @@ return array(
'Rector\\Doctrine\\NodeFactory\\RepositoryNodeFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/RepositoryNodeFactory.php',
'Rector\\Doctrine\\NodeFactory\\TranslationClassNodeFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/TranslationClassNodeFactory.php',
'Rector\\Doctrine\\NodeFactory\\ValueAssignFactory' => $vendorDir . '/rector/rector-doctrine/src/NodeFactory/ValueAssignFactory.php',
'Rector\\Doctrine\\NodeManipulator\\ColumnPropertyTypeResolver' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/ColumnPropertyTypeResolver.php',
'Rector\\Doctrine\\NodeManipulator\\ConstructorManipulator' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/ConstructorManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\DependencyRemover' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/DependencyRemover.php',
'Rector\\Doctrine\\NodeManipulator\\DoctrineItemDefaultValueManipulator' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/DoctrineItemDefaultValueManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\IssetDimFetchCleaner' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/IssetDimFetchCleaner.php',
'Rector\\Doctrine\\NodeManipulator\\PropertyTypeManipulator' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/PropertyTypeManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\ToManyRelationPropertyTypeResolver' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/ToManyRelationPropertyTypeResolver.php',
'Rector\\Doctrine\\NodeManipulator\\ToOneRelationPropertyTypeResolver' => $vendorDir . '/rector/rector-doctrine/src/NodeManipulator/ToOneRelationPropertyTypeResolver.php',
'Rector\\Doctrine\\PhpDocParser\\DoctrineDocBlockResolver' => $vendorDir . '/rector/rector-doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php',
'Rector\\Doctrine\\PhpDoc\\ShortClassExpander' => $vendorDir . '/rector/rector-doctrine/src/PhpDoc/ShortClassExpander.php',
'Rector\\Doctrine\\Rector\\ClassMethod\\MakeEntitySetterNullabilityInSyncWithPropertyRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/ClassMethod/MakeEntitySetterNullabilityInSyncWithPropertyRector.php',
'Rector\\Doctrine\\Rector\\ClassMethod\\ServiceEntityRepositoryParentCallToDIRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/ClassMethod/ServiceEntityRepositoryParentCallToDIRector.php',
'Rector\\Doctrine\\Rector\\Class_\\AddEntityIdByConditionRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Class_/AddEntityIdByConditionRector.php',
@ -1924,6 +1928,9 @@ return array(
'Rector\\Doctrine\\Rector\\Property\\ImproveDoctrineCollectionDocTypeInEntityRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php',
'Rector\\Doctrine\\Rector\\Property\\MakeEntityDateTimePropertyDateTimeInterfaceRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/MakeEntityDateTimePropertyDateTimeInterfaceRector.php',
'Rector\\Doctrine\\Rector\\Property\\RemoveRedundantDefaultPropertyAnnotationValuesRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/RemoveRedundantDefaultPropertyAnnotationValuesRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromColumnTypeRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromColumnTypeRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromToManyRelationTypeRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromToManyRelationTypeRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromToOneRelationTypeRector' => $vendorDir . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromToOneRelationTypeRector.php',
'Rector\\Doctrine\\Set\\DoctrineSetList' => $vendorDir . '/rector/rector-doctrine/src/Set/DoctrineSetList.php',
'Rector\\Doctrine\\TypeAnalyzer\\CollectionTypeFactory' => $vendorDir . '/rector/rector-doctrine/src/TypeAnalyzer/CollectionTypeFactory.php',
'Rector\\Doctrine\\TypeAnalyzer\\CollectionTypeResolver' => $vendorDir . '/rector/rector-doctrine/src/TypeAnalyzer/CollectionTypeResolver.php',
@ -3049,7 +3056,6 @@ return array(
'Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier' => $baseDir . '/rules/TypeDeclaration/PHPStan/Type/ObjectTypeSpecifier.php',
'Rector\\TypeDeclaration\\PhpDocParser\\NonInformativeReturnTagRemover' => $baseDir . '/rules/TypeDeclaration/PhpDocParser/NonInformativeReturnTagRemover.php',
'Rector\\TypeDeclaration\\PhpDocParser\\ParamPhpDocNodeFactory' => $baseDir . '/rules/TypeDeclaration/PhpDocParser/ParamPhpDocNodeFactory.php',
'Rector\\TypeDeclaration\\PhpDoc\\ShortClassExpander' => $baseDir . '/rules/TypeDeclaration/PhpDoc/ShortClassExpander.php',
'Rector\\TypeDeclaration\\PhpParserTypeAnalyzer' => $baseDir . '/rules/TypeDeclaration/PhpParserTypeAnalyzer.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddArrayParamDocTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/AddArrayParamDocTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddArrayReturnDocTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/AddArrayReturnDocTypeRector.php',
@ -3090,7 +3096,6 @@ return array(
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\AllAssignNodePropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/AllAssignNodePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\ConstructorPropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/ConstructorPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DefaultValuePropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DefaultValuePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DoctrineRelationPropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DoctrineRelationPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\GetterTypeDeclarationPropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterTypeDeclarationPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\VarDocPropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/VarDocPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ReturnTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061
class ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,19 +42,19 @@ class ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequiref98a46415524cbcbf0a0503e7dd3f061($fileIdentifier, $file);
composerRequire179611c6f2ea972f3669c2fd86d0857c($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequiref98a46415524cbcbf0a0503e7dd3f061($fileIdentifier, $file)
function composerRequire179611c6f2ea972f3669c2fd86d0857c($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
class ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@ -2288,12 +2288,16 @@ class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
'Rector\\Doctrine\\NodeFactory\\RepositoryNodeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/RepositoryNodeFactory.php',
'Rector\\Doctrine\\NodeFactory\\TranslationClassNodeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/TranslationClassNodeFactory.php',
'Rector\\Doctrine\\NodeFactory\\ValueAssignFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeFactory/ValueAssignFactory.php',
'Rector\\Doctrine\\NodeManipulator\\ColumnPropertyTypeResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/ColumnPropertyTypeResolver.php',
'Rector\\Doctrine\\NodeManipulator\\ConstructorManipulator' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/ConstructorManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\DependencyRemover' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/DependencyRemover.php',
'Rector\\Doctrine\\NodeManipulator\\DoctrineItemDefaultValueManipulator' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/DoctrineItemDefaultValueManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\IssetDimFetchCleaner' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/IssetDimFetchCleaner.php',
'Rector\\Doctrine\\NodeManipulator\\PropertyTypeManipulator' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/PropertyTypeManipulator.php',
'Rector\\Doctrine\\NodeManipulator\\ToManyRelationPropertyTypeResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/ToManyRelationPropertyTypeResolver.php',
'Rector\\Doctrine\\NodeManipulator\\ToOneRelationPropertyTypeResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/NodeManipulator/ToOneRelationPropertyTypeResolver.php',
'Rector\\Doctrine\\PhpDocParser\\DoctrineDocBlockResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php',
'Rector\\Doctrine\\PhpDoc\\ShortClassExpander' => __DIR__ . '/..' . '/rector/rector-doctrine/src/PhpDoc/ShortClassExpander.php',
'Rector\\Doctrine\\Rector\\ClassMethod\\MakeEntitySetterNullabilityInSyncWithPropertyRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/ClassMethod/MakeEntitySetterNullabilityInSyncWithPropertyRector.php',
'Rector\\Doctrine\\Rector\\ClassMethod\\ServiceEntityRepositoryParentCallToDIRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/ClassMethod/ServiceEntityRepositoryParentCallToDIRector.php',
'Rector\\Doctrine\\Rector\\Class_\\AddEntityIdByConditionRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Class_/AddEntityIdByConditionRector.php',
@ -2319,6 +2323,9 @@ class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
'Rector\\Doctrine\\Rector\\Property\\ImproveDoctrineCollectionDocTypeInEntityRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/ImproveDoctrineCollectionDocTypeInEntityRector.php',
'Rector\\Doctrine\\Rector\\Property\\MakeEntityDateTimePropertyDateTimeInterfaceRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/MakeEntityDateTimePropertyDateTimeInterfaceRector.php',
'Rector\\Doctrine\\Rector\\Property\\RemoveRedundantDefaultPropertyAnnotationValuesRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/RemoveRedundantDefaultPropertyAnnotationValuesRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromColumnTypeRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromColumnTypeRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromToManyRelationTypeRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromToManyRelationTypeRector.php',
'Rector\\Doctrine\\Rector\\Property\\TypedPropertyFromToOneRelationTypeRector' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Rector/Property/TypedPropertyFromToOneRelationTypeRector.php',
'Rector\\Doctrine\\Set\\DoctrineSetList' => __DIR__ . '/..' . '/rector/rector-doctrine/src/Set/DoctrineSetList.php',
'Rector\\Doctrine\\TypeAnalyzer\\CollectionTypeFactory' => __DIR__ . '/..' . '/rector/rector-doctrine/src/TypeAnalyzer/CollectionTypeFactory.php',
'Rector\\Doctrine\\TypeAnalyzer\\CollectionTypeResolver' => __DIR__ . '/..' . '/rector/rector-doctrine/src/TypeAnalyzer/CollectionTypeResolver.php',
@ -3444,7 +3451,6 @@ class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
'Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PHPStan/Type/ObjectTypeSpecifier.php',
'Rector\\TypeDeclaration\\PhpDocParser\\NonInformativeReturnTagRemover' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PhpDocParser/NonInformativeReturnTagRemover.php',
'Rector\\TypeDeclaration\\PhpDocParser\\ParamPhpDocNodeFactory' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PhpDocParser/ParamPhpDocNodeFactory.php',
'Rector\\TypeDeclaration\\PhpDoc\\ShortClassExpander' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PhpDoc/ShortClassExpander.php',
'Rector\\TypeDeclaration\\PhpParserTypeAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/PhpParserTypeAnalyzer.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddArrayParamDocTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/AddArrayParamDocTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\AddArrayReturnDocTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/AddArrayReturnDocTypeRector.php',
@ -3485,7 +3491,6 @@ class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\AllAssignNodePropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/AllAssignNodePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\ConstructorPropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/ConstructorPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DefaultValuePropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DefaultValuePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DoctrineRelationPropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DoctrineRelationPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\GetterTypeDeclarationPropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterTypeDeclarationPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\VarDocPropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/VarDocPropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ReturnTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/ReturnTypeInferer.php',
@ -3820,9 +3825,9 @@ class ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitf98a46415524cbcbf0a0503e7dd3f061::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit179611c6f2ea972f3669c2fd86d0857c::$classMap;
}, null, ClassLoader::class);
}

View File

@ -2171,16 +2171,16 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "719b3a283babd1f880adb50df2754ec429371120"
"reference": "23719cb470738f51ea0a3646a59106ff2ea7de52"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/719b3a283babd1f880adb50df2754ec429371120",
"reference": "719b3a283babd1f880adb50df2754ec429371120",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/23719cb470738f51ea0a3646a59106ff2ea7de52",
"reference": "23719cb470738f51ea0a3646a59106ff2ea7de52",
"shasum": ""
},
"require": {
"php": ">=8.0"
"php": ">=8.1"
},
"conflict": {
"rector\/rector": "<0.11"
@ -2201,7 +2201,7 @@
"symplify\/rule-doc-generator": "^10.0",
"symplify\/vendor-patches": "^10.0"
},
"time": "2021-12-15T00:53:40+00:00",
"time": "2021-12-15T16:44:14+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 584d84b'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 719b3a2'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 36d651e'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 4fb1137'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 1e3b3ab'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 47298f7'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 1de3f30'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 0a50dc4'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main b35b928'));
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 584d84b'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 23719cb'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 36d651e'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 4fb1137'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 1e3b3ab'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 47298f7'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 1de3f30'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 0a50dc4'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main b35b928'));
private function __construct()
{
}

View File

@ -4,7 +4,7 @@
"license": "MIT",
"description": "Rector upgrades rules for Doctrine",
"require": {
"php": ">=8.0"
"php": ">=8.1"
},
"require-dev": {
"phpstan\/extension-installer": "^1.1",
@ -41,7 +41,7 @@
"check-cs": "vendor\/bin\/ecs check --ansi",
"fix-cs": "vendor\/bin\/ecs check --fix --ansi",
"docs": [
"vendor\/bin\/rule-doc-generator generate src --output-file docs\/rector_rules_overview.md --ansi",
"vendor\/bin\/rule-doc-generator generate src --output-file docs\/rector_rules_overview.md --ansi --configure-method",
"vendor\/bin\/ecs check-markdown docs\/rector_rules_overview.md --ansi --fix"
]
},

View File

@ -13,6 +13,9 @@ use Rector\Doctrine\Rector\Property\CorrectDefaultTypesOnEntityPropertyRector;
use Rector\Doctrine\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector;
use Rector\Doctrine\Rector\Property\MakeEntityDateTimePropertyDateTimeInterfaceRector;
use Rector\Doctrine\Rector\Property\RemoveRedundantDefaultPropertyAnnotationValuesRector;
use Rector\Doctrine\Rector\Property\TypedPropertyFromColumnTypeRector;
use Rector\Doctrine\Rector\Property\TypedPropertyFromToManyRelationTypeRector;
use Rector\Doctrine\Rector\Property\TypedPropertyFromToOneRelationTypeRector;
use Rector\Privatization\Rector\MethodCall\ReplaceStringWithClassConstantRector;
use Rector\Privatization\ValueObject\ReplaceStringWithClassConstant;
use Rector\Transform\Rector\Attribute\AttributeKeyToClassConstFetchRector;
@ -32,6 +35,10 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
$services->set(\Rector\Doctrine\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector::class);
$services->set(\Rector\Doctrine\Rector\Property\RemoveRedundantDefaultPropertyAnnotationValuesRector::class);
$services->set(\Rector\Doctrine\Rector\Class_\RemoveRedundantDefaultClassAnnotationValuesRector::class);
// typed properties in entities from annotations/attributes
$services->set(\Rector\Doctrine\Rector\Property\TypedPropertyFromColumnTypeRector::class);
$services->set(\Rector\Doctrine\Rector\Property\TypedPropertyFromToOneRelationTypeRector::class);
$services->set(\Rector\Doctrine\Rector\Property\TypedPropertyFromToManyRelationTypeRector::class);
$services->set(\Rector\Transform\Rector\Attribute\AttributeKeyToClassConstFetchRector::class)->configure([new \Rector\Transform\ValueObject\AttributeKeyToClassConstFetch('Doctrine\\ORM\\Mapping\\Column', 'type', 'Doctrine\\DBAL\\Types\\Types', ['array' => 'ARRAY', 'ascii_string' => 'ASCII_STRING', 'bigint' => 'BIGINT', 'binary' => 'BINARY', 'blob' => 'BLOB', 'boolean' => 'BOOLEAN', 'date' => 'DATE_MUTABLE', 'date_immutable' => 'DATE_IMMUTABLE', 'dateinterval' => 'DATEINTERVAL', 'datetime' => 'DATETIME_MUTABLE', 'datetime_immutable' => 'DATETIME_IMMUTABLE', 'datetimetz' => 'DATETIMETZ_MUTABLE', 'datetimetz_immutable' => 'DATETIMETZ_IMMUTABLE', 'decimal' => 'DECIMAL', 'float' => 'FLOAT', 'guid' => 'GUID', 'integer' => 'INTEGER', 'json' => 'JSON', 'object' => 'OBJECT', 'simple_array' => 'SIMPLE_ARRAY', 'smallint' => 'SMALLINT', 'string' => 'STRING', 'text' => 'TEXT', 'time' => 'TIME_MUTABLE', 'time_immutable' => 'TIME_IMMUTABLE'])]);
$services->set(\Rector\Privatization\Rector\MethodCall\ReplaceStringWithClassConstantRector::class)->configure([new \Rector\Privatization\ValueObject\ReplaceStringWithClassConstant('Doctrine\\ORM\\QueryBuilder', 'orderBy', 1, 'Doctrine\\Common\\Collections\\Criteria', \true), new \Rector\Privatization\ValueObject\ReplaceStringWithClassConstant('Doctrine\\ORM\\QueryBuilder', 'addOrderBy', 1, 'Doctrine\\Common\\Collections\\Criteria', \true)]);
$services->set(\Rector\Transform\Rector\MethodCall\ServiceGetterToConstructorInjectionRector::class)->configure([new \Rector\Transform\ValueObject\ServiceGetterToConstructorInjection('Doctrine\\Common\\Persistence\\ManagerRegistry', 'getConnection', 'Doctrine\\DBAL\\Connection'), new \Rector\Transform\ValueObject\ServiceGetterToConstructorInjection('Doctrine\\ORM\\EntityManagerInterface', 'getConfiguration', 'Doctrine\\ORM\\Configuration')]);

View File

@ -1,4 +1,4 @@
# 24 Rules Overview
# 28 Rules Overview
## AddEntityIdByConditionRector
@ -17,17 +17,19 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(AddEntityIdByConditionRector::class)
->configure([
AddEntityIdByConditionRector::DETECTED_TRAITS => [
'Knp\DoctrineBehaviors\Model\Translatable\Translation',
'Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait',
],
]]);
AddEntityIdByConditionRector::DETECTED_TRAITS => [
'Knp\DoctrineBehaviors\Model\Translatable\Translation',
'Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait',
],
]);
};
```
```diff
+use Doctrine\ORM\Mapping as ORM;
+
class SomeClass
{
use SomeTrait;
@ -160,6 +162,37 @@ Change array to ArrayCollection in setParameters method of query builder
<br>
## ClassAnnotationToNamedArgumentConstructorRector
Decorate classic array-based class annotation with named parameters
- class: [`Rector\Doctrine\Rector\Class_\ClassAnnotationToNamedArgumentConstructorRector`](../src/Rector/Class_/ClassAnnotationToNamedArgumentConstructorRector.php)
```diff
+use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
+
/**
* @Annotation
+ * @NamedArgumentConstructor
*/
class SomeAnnotation
{
/**
* @var string
*/
private $foo;
- public function __construct(array $values)
+ public function __construct(string $foo)
{
- $this->foo = $values['foo'];
+ $this->foo = $foo;
}
}
```
<br>
## CorrectDefaultTypesOnEntityPropertyRector
Change default value types to match Doctrine annotation type
@ -201,10 +234,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(EntityAliasToClassConstantReferenceRector::class)
->configure([
EntityAliasToClassConstantReferenceRector::ALIASES_TO_NAMESPACES => [
'App' => 'App\Entity',
EntityAliasToClassConstantReferenceRector::ALIASES_TO_NAMESPACES => [
'App' => 'App\Entity',
], ]]);
],
]);
};
```
@ -234,9 +268,9 @@ Improve @var, `@param` and `@return` types for Doctrine collections to make them
class SomeClass
{
/**
* @ORM\OneToMany(targetEntity=Training::class, mappedBy="trainer")
* @ORM\OneToMany(targetEntity=Trainer::class, mappedBy="trainer")
- * @var Collection|Trainer[]
+ * @var Collection<int, Training>|Trainer[]
+ * @var Collection<int, Trainer>|Trainer[]
*/
private $trainings = [];
}
@ -307,7 +341,7 @@ Change Loggable from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
Make maker bundle generate DateTime property accept DateTimeInterface too
- class: [`Rector\Doctrine\Rector\Property\MakeEntityDateTimePropertyDateTimeInterfaceRector`](../src/Rector/ClassMethod/MakeEntityDateTimePropertyDateTimeInterfaceRector.php)
- class: [`Rector\Doctrine\Rector\Property\MakeEntityDateTimePropertyDateTimeInterfaceRector`](../src/Rector/Property/MakeEntityDateTimePropertyDateTimeInterfaceRector.php)
```diff
use Doctrine\ORM\Mapping as ORM;
@ -711,18 +745,9 @@ Change Translation from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
* @ORM\Column(length=128)
*/
private $title;
/**
- * @Gedmo\Translatable
* @ORM\Column(type="text")
*/
private $content;
-
- /**
- * @Gedmo\Locale
- * Used locale to override Translation listener`s locale
- * this is not a mapped field of entity metadata, just a simple property
- * and it is not necessary because globally locale can be set in listener
- */
- private $locale;
-
@ -736,16 +761,6 @@ Change Translation from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
- return $this->title;
- }
-
- public function setContent($content)
- {
- $this->content = $content;
- }
-
- public function getContent()
- {
- return $this->content;
- }
-
- public function setTranslatableLocale($locale)
- {
- $this->locale = $locale;
@ -835,3 +850,67 @@ Change Tree from gedmo/doctrine-extensions to knplabs/doctrine-behaviors
```
<br>
## TypedPropertyFromColumnTypeRector
Complete `@var` annotations or types based on @ORM\Column
- class: [`Rector\Doctrine\Rector\Property\TypedPropertyFromColumnTypeRector`](../src/Rector/Property/TypedPropertyFromColumnTypeRector.php)
```diff
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\Column(type="string")
*/
- private $name;
+ private string|null $name = null;
}
```
<br>
## TypedPropertyFromToManyRelationTypeRector
Complete `@var` annotations or types based on @ORM\*toMany annotations or attributes
- class: [`Rector\Doctrine\Rector\Property\TypedPropertyFromToManyRelationTypeRector`](../src/Rector/Property/TypedPropertyFromToManyRelationTypeRector.php)
```diff
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToMany(targetEntity="App\Product")
+ * @var \Doctrine\Common\Collections\Collection<\App\Product>
*/
- private $products;
+ private \Doctrine\Common\Collections\Collection $products;
}
```
<br>
## TypedPropertyFromToOneRelationTypeRector
Complete `@var` annotations or types based on @ORM\*toOne annotations or attributes
- class: [`Rector\Doctrine\Rector\Property\TypedPropertyFromToOneRelationTypeRector`](../src/Rector/Property/TypedPropertyFromToOneRelationTypeRector.php)
```diff
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToOne(targetEntity="App\Company\Entity\Company")
*/
- private $company;
+ private ?\App\Company\Entity\Company $company = null;
}
```
<br>

View File

@ -0,0 +1,107 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\NodeManipulator;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
final class ColumnPropertyTypeResolver
{
/**
* @var string
*/
private const DATE_TIME_INTERFACE = 'DateTimeInterface';
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @var \Rector\NodeTypeResolver\PHPStan\Type\TypeFactory
*/
private $typeFactory;
/**
* @var array<string, \PHPStan\Type\Type>
*/
private $doctrineTypeToScalarType;
/**
* @param array<string, Type> $doctrineTypeToScalarType
* @see https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/basic-mapping.html#doctrine-mapping-types
*/
public function __construct(\Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\NodeTypeResolver\PHPStan\Type\TypeFactory $typeFactory, array $doctrineTypeToScalarType = null)
{
$doctrineTypeToScalarType = $doctrineTypeToScalarType ?? [
'tinyint' => new \PHPStan\Type\BooleanType(),
// integers
'smallint' => new \PHPStan\Type\IntegerType(),
'mediumint' => new \PHPStan\Type\IntegerType(),
'int' => new \PHPStan\Type\IntegerType(),
'integer' => new \PHPStan\Type\IntegerType(),
'bigint' => new \PHPStan\Type\IntegerType(),
'numeric' => new \PHPStan\Type\IntegerType(),
// floats
'decimal' => new \PHPStan\Type\FloatType(),
'float' => new \PHPStan\Type\FloatType(),
'double' => new \PHPStan\Type\FloatType(),
'real' => new \PHPStan\Type\FloatType(),
// strings
'tinytext' => new \PHPStan\Type\StringType(),
'mediumtext' => new \PHPStan\Type\StringType(),
'longtext' => new \PHPStan\Type\StringType(),
'text' => new \PHPStan\Type\StringType(),
'varchar' => new \PHPStan\Type\StringType(),
'string' => new \PHPStan\Type\StringType(),
'char' => new \PHPStan\Type\StringType(),
'longblob' => new \PHPStan\Type\StringType(),
'blob' => new \PHPStan\Type\StringType(),
'mediumblob' => new \PHPStan\Type\StringType(),
'tinyblob' => new \PHPStan\Type\StringType(),
'binary' => new \PHPStan\Type\StringType(),
'varbinary' => new \PHPStan\Type\StringType(),
'set' => new \PHPStan\Type\StringType(),
// date time objects
'date' => new \PHPStan\Type\ObjectType(self::DATE_TIME_INTERFACE),
'datetime' => new \PHPStan\Type\ObjectType(self::DATE_TIME_INTERFACE),
'timestamp' => new \PHPStan\Type\ObjectType(self::DATE_TIME_INTERFACE),
'time' => new \PHPStan\Type\ObjectType(self::DATE_TIME_INTERFACE),
'year' => new \PHPStan\Type\ObjectType(self::DATE_TIME_INTERFACE),
];
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->typeFactory = $typeFactory;
$this->doctrineTypeToScalarType = $doctrineTypeToScalarType;
}
public function resolve(\PhpParser\Node\Stmt\Property $property) : ?\PHPStan\Type\Type
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
$doctrineAnnotationTagValueNode = $phpDocInfo->findOneByAnnotationClass('Doctrine\\ORM\\Mapping\\Column');
if (!$doctrineAnnotationTagValueNode instanceof \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode) {
return null;
}
$type = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
if ($type === null) {
return new \PHPStan\Type\MixedType();
}
$scalarType = $this->doctrineTypeToScalarType[$type] ?? null;
if (!$scalarType instanceof \PHPStan\Type\Type) {
return new \PHPStan\Type\MixedType();
}
$types = [$scalarType];
$isNullable = $doctrineAnnotationTagValueNode->getValue('nullable');
// is nullable?
if ($isNullable instanceof \PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode) {
$types[] = new \PHPStan\Type\NullType();
}
return $this->typeFactory->createMixedPassedOrUnionType($types);
}
}

View File

@ -0,0 +1,53 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\NodeManipulator;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Doctrine\PhpDoc\ShortClassExpander;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
final class ToManyRelationPropertyTypeResolver
{
/**
* @var string
*/
private const COLLECTION_TYPE = 'Doctrine\\Common\\Collections\\Collection';
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @readonly
* @var \Rector\Doctrine\PhpDoc\ShortClassExpander
*/
private $shortClassExpander;
public function __construct(\Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\Doctrine\PhpDoc\ShortClassExpander $shortClassExpander)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->shortClassExpander = $shortClassExpander;
}
public function resolve(\PhpParser\Node\Stmt\Property $property) : ?\PHPStan\Type\Type
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
$toManyRelationTagValueNode = $phpDocInfo->getByAnnotationClasses(['Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany']);
if ($toManyRelationTagValueNode !== null) {
return $this->processToManyRelation($property, $toManyRelationTagValueNode);
}
return null;
}
private function processToManyRelation(\PhpParser\Node\Stmt\Property $property, \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : \PHPStan\Type\Type
{
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
if (!\is_string($targetEntity)) {
return new \Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType(self::COLLECTION_TYPE);
}
$entityFullyQualifiedClass = $this->shortClassExpander->resolveFqnTargetEntity($targetEntity, $property);
$relatedEntityType = new \Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType($entityFullyQualifiedClass);
return new \PHPStan\Type\Generic\GenericObjectType(self::COLLECTION_TYPE, [$relatedEntityType]);
}
}

View File

@ -1,31 +1,22 @@
<?php
declare (strict_types=1);
namespace Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
namespace Rector\Doctrine\NodeManipulator;
use RectorPrefix20211215\Nette\Utils\Strings;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
use Rector\TypeDeclaration\PhpDoc\ShortClassExpander;
/**
* @deprecated Move to rector-doctrine, under code quality
*/
final class DoctrineRelationPropertyTypeInferer implements \Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface
final class ToOneRelationPropertyTypeResolver
{
/**
* @var string
*/
private const COLLECTION_TYPE = 'Doctrine\\Common\\Collections\\Collection';
/**
* @readonly
* @var \Rector\NodeTypeResolver\PHPStan\Type\TypeFactory
@ -36,30 +27,20 @@ final class DoctrineRelationPropertyTypeInferer implements \Rector\TypeDeclarati
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @readonly
* @var \Rector\TypeDeclaration\PhpDoc\ShortClassExpander
*/
private $shortClassExpander;
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher
*/
private $classAnnotationMatcher;
public function __construct(\Rector\NodeTypeResolver\PHPStan\Type\TypeFactory $typeFactory, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\TypeDeclaration\PhpDoc\ShortClassExpander $shortClassExpander, \Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher $classAnnotationMatcher)
public function __construct(\Rector\NodeTypeResolver\PHPStan\Type\TypeFactory $typeFactory, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher $classAnnotationMatcher)
{
$this->typeFactory = $typeFactory;
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->shortClassExpander = $shortClassExpander;
$this->classAnnotationMatcher = $classAnnotationMatcher;
}
public function inferProperty(\PhpParser\Node\Stmt\Property $property) : ?\PHPStan\Type\Type
public function resolve(\PhpParser\Node\Stmt\Property $property) : ?\PHPStan\Type\Type
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
$toManyRelationTagValueNode = $phpDocInfo->getByAnnotationClasses(['Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany']);
if ($toManyRelationTagValueNode !== null) {
return $this->processToManyRelation($property, $toManyRelationTagValueNode);
}
$toOneRelationTagValueNode = $phpDocInfo->getByAnnotationClasses(['Doctrine\\ORM\\Mapping\\ManyToOne', 'Doctrine\\ORM\\Mapping\\OneToOne']);
if ($toOneRelationTagValueNode !== null) {
$joinDoctrineAnnotationTagValueNode = $phpDocInfo->findOneByAnnotationClass('Doctrine\\ORM\\Mapping\\JoinColumn');
@ -67,25 +48,10 @@ final class DoctrineRelationPropertyTypeInferer implements \Rector\TypeDeclarati
}
return null;
}
public function getPriority() : int
{
return 2100;
}
private function processToManyRelation(\PhpParser\Node\Stmt\Property $property, \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : \PHPStan\Type\Type
{
$types = [];
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
if (\is_string($targetEntity)) {
$entityFullyQualifiedClass = $this->shortClassExpander->resolveFqnTargetEntity($targetEntity, $property);
$types[] = new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType($entityFullyQualifiedClass));
}
$types[] = new \Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType(self::COLLECTION_TYPE);
return $this->typeFactory->createMixedPassedOrUnionType($types);
}
private function processToOneRelation(\PhpParser\Node\Stmt\Property $property, \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $toOneDoctrineAnnotationTagValueNode, ?\Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $joinDoctrineAnnotationTagValueNode) : \PHPStan\Type\Type
{
$targetEntity = $toOneDoctrineAnnotationTagValueNode->getValueWithoutQuotes('targetEntity');
if ($targetEntity === null) {
if (!\is_string($targetEntity)) {
return new \PHPStan\Type\MixedType();
}
if (\substr_compare($targetEntity, '::class', -\strlen('::class')) === 0) {
@ -95,16 +61,18 @@ final class DoctrineRelationPropertyTypeInferer implements \Rector\TypeDeclarati
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntity, $property);
$types = [];
$types[] = new \Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType($tagFullyQualifiedName);
if ($this->shouldAddNullType($joinDoctrineAnnotationTagValueNode)) {
if ($joinDoctrineAnnotationTagValueNode instanceof \Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode && $this->shouldAddNullType($joinDoctrineAnnotationTagValueNode)) {
$types[] = new \PHPStan\Type\NullType();
}
return $this->typeFactory->createMixedPassedOrUnionType($types);
}
private function shouldAddNullType(?\Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : bool
{
if ($doctrineAnnotationTagValueNode === null) {
return \true;
$propertyType = $this->typeFactory->createMixedPassedOrUnionType($types);
// add default null if missing
if (!\PHPStan\Type\TypeCombinator::containsNull($propertyType)) {
$propertyType = \PHPStan\Type\TypeCombinator::addNull($propertyType);
}
return $propertyType;
}
private function shouldAddNullType(\Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode) : bool
{
$isNullableValue = $doctrineAnnotationTagValueNode->getValue('nullable');
return $isNullableValue instanceof \PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode;
}

View File

@ -1,7 +1,7 @@
<?php
declare (strict_types=1);
namespace Rector\TypeDeclaration\PhpDoc;
namespace Rector\Doctrine\PhpDoc;
use RectorPrefix20211215\Nette\Utils\Strings;
use PhpParser\Node;
@ -33,6 +33,9 @@ final class ShortClassExpander
$this->reflectionProvider = $reflectionProvider;
$this->objectTypeSpecifier = $objectTypeSpecifier;
}
/**
* @api
*/
public function resolveFqnTargetEntity(string $targetEntity, \PhpParser\Node $node) : string
{
$targetEntity = $this->getCleanedUpTargetEntity($targetEntity);

View File

@ -9,7 +9,7 @@ use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\TypeDeclaration\PhpDoc\ShortClassExpander;
use Rector\Doctrine\PhpDoc\ShortClassExpander;
final class DoctrineDocBlockResolver
{
/**
@ -17,14 +17,14 @@ final class DoctrineDocBlockResolver
*/
private $phpDocInfoFactory;
/**
* @var \Rector\TypeDeclaration\PhpDoc\ShortClassExpander
* @var \Rector\Doctrine\PhpDoc\ShortClassExpander
*/
private $shortClassExpander;
/**
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
*/
private $betterNodeFinder;
public function __construct(\Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\TypeDeclaration\PhpDoc\ShortClassExpander $shortClassExpander, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder)
public function __construct(\Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\Doctrine\PhpDoc\ShortClassExpander $shortClassExpander, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->shortClassExpander = $shortClassExpander;

View File

@ -0,0 +1,109 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Doctrine\NodeManipulator\ColumnPropertyTypeResolver;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Doctrine\Tests\Rector\Property\TypedPropertyFromColumnTypeRector\TypedPropertyFromColumnTypeRectorTest
*/
final class TypedPropertyFromColumnTypeRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @var \Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator
*/
private $propertyTypeDecorator;
/**
* @var \Rector\Doctrine\NodeManipulator\ColumnPropertyTypeResolver
*/
private $columnPropertyTypeResolver;
/**
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
*/
private $phpDocTypeChanger;
public function __construct(\Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator $propertyTypeDecorator, \Rector\Doctrine\NodeManipulator\ColumnPropertyTypeResolver $columnPropertyTypeResolver, \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger $phpDocTypeChanger)
{
$this->propertyTypeDecorator = $propertyTypeDecorator;
$this->columnPropertyTypeResolver = $columnPropertyTypeResolver;
$this->phpDocTypeChanger = $phpDocTypeChanger;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Complete @var annotations or types based on @ORM\\Column', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\Column(type="string")
*/
private $name;
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\Column(type="string")
*/
private string|null $name = null;
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Property::class];
}
/**
* @param Property $node
* @return \PhpParser\Node\Stmt\Property|null
*/
public function refactor(\PhpParser\Node $node)
{
if ($node->type !== null) {
return null;
}
$propertyType = $this->columnPropertyTypeResolver->resolve($node);
if (!$propertyType instanceof \PHPStan\Type\Type || $propertyType instanceof \PHPStan\Type\MixedType) {
return null;
}
// add default null if missing
if (!\PHPStan\Type\TypeCombinator::containsNull($propertyType)) {
$propertyType = \PHPStan\Type\TypeCombinator::addNull($propertyType);
}
$typeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($propertyType, \Rector\PHPStanStaticTypeMapper\Enum\TypeKind::PROPERTY());
if ($typeNode === null) {
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
if ($this->phpVersionProvider->isAtLeastPhpVersion(\Rector\Core\ValueObject\PhpVersion::PHP_74)) {
if ($propertyType instanceof \PHPStan\Type\UnionType) {
$this->propertyTypeDecorator->decoratePropertyUnionType($propertyType, $typeNode, $node, $phpDocInfo);
return $node;
}
$node->type = $typeNode;
return $node;
}
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $propertyType);
return $node;
}
}

View File

@ -0,0 +1,106 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Doctrine\NodeManipulator\ToManyRelationPropertyTypeResolver;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Doctrine\Tests\Rector\Property\TypedPropertyFromToManyRelationTypeRector\TypedPropertyFromToManyRelationTypeRectorTest
*/
final class TypedPropertyFromToManyRelationTypeRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @var \Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator
*/
private $propertyTypeDecorator;
/**
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
*/
private $phpDocTypeChanger;
/**
* @var \Rector\Doctrine\NodeManipulator\ToManyRelationPropertyTypeResolver
*/
private $toManyRelationPropertyTypeResolver;
public function __construct(\Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator $propertyTypeDecorator, \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger $phpDocTypeChanger, \Rector\Doctrine\NodeManipulator\ToManyRelationPropertyTypeResolver $toManyRelationPropertyTypeResolver)
{
$this->propertyTypeDecorator = $propertyTypeDecorator;
$this->phpDocTypeChanger = $phpDocTypeChanger;
$this->toManyRelationPropertyTypeResolver = $toManyRelationPropertyTypeResolver;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Complete @var annotations or types based on @ORM\\*toMany annotations or attributes', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToMany(targetEntity="App\Product")
*/
private $products;
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToMany(targetEntity="App\Product")
* @var \Doctrine\Common\Collections\Collection<\App\Product>
*/
private \Doctrine\Common\Collections\Collection $products;
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Property::class];
}
/**
* @param Property $node
* @return \PhpParser\Node\Stmt\Property|null
*/
public function refactor(\PhpParser\Node $node)
{
if ($node->type !== null) {
return null;
}
$propertyType = $this->toManyRelationPropertyTypeResolver->resolve($node);
if (!$propertyType instanceof \PHPStan\Type\Type || $propertyType instanceof \PHPStan\Type\MixedType) {
return null;
}
$typeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($propertyType, \Rector\PHPStanStaticTypeMapper\Enum\TypeKind::PROPERTY());
if ($typeNode === null) {
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
// always decorate with collection generic type
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $propertyType);
if ($this->phpVersionProvider->isAtLeastPhpVersion(\Rector\Core\ValueObject\PhpVersion::PHP_74)) {
if ($propertyType instanceof \PHPStan\Type\UnionType) {
$this->propertyTypeDecorator->decoratePropertyUnionType($propertyType, $typeNode, $node, $phpDocInfo);
return $node;
}
$node->type = $typeNode;
return $node;
}
return $node;
}
}

View File

@ -0,0 +1,104 @@
<?php
declare (strict_types=1);
namespace Rector\Doctrine\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Doctrine\NodeManipulator\ToOneRelationPropertyTypeResolver;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Doctrine\Tests\Rector\Property\TypedPropertyFromToOneRelationTypeRector\TypedPropertyFromToOneRelationTypeRectorTest
*/
final class TypedPropertyFromToOneRelationTypeRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @var \Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator
*/
private $propertyTypeDecorator;
/**
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
*/
private $phpDocTypeChanger;
/**
* @var \Rector\Doctrine\NodeManipulator\ToOneRelationPropertyTypeResolver
*/
private $toOneRelationPropertyTypeResolver;
public function __construct(\Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator $propertyTypeDecorator, \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger $phpDocTypeChanger, \Rector\Doctrine\NodeManipulator\ToOneRelationPropertyTypeResolver $toOneRelationPropertyTypeResolver)
{
$this->propertyTypeDecorator = $propertyTypeDecorator;
$this->phpDocTypeChanger = $phpDocTypeChanger;
$this->toOneRelationPropertyTypeResolver = $toOneRelationPropertyTypeResolver;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Complete @var annotations or types based on @ORM\\*toOne annotations or attributes', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToOne(targetEntity="App\Company\Entity\Company")
*/
private $company;
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
class SimpleColumn
{
/**
* @ORM\OneToOne(targetEntity="App\Company\Entity\Company")
*/
private ?\App\Company\Entity\Company $company = null;
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Property::class];
}
/**
* @param Property $node
* @return \PhpParser\Node\Stmt\Property|null
*/
public function refactor(\PhpParser\Node $node)
{
if ($node->type !== null) {
return null;
}
$propertyType = $this->toOneRelationPropertyTypeResolver->resolve($node);
if (!$propertyType instanceof \PHPStan\Type\Type || $propertyType instanceof \PHPStan\Type\MixedType) {
return null;
}
$typeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($propertyType, \Rector\PHPStanStaticTypeMapper\Enum\TypeKind::PROPERTY());
if ($typeNode === null) {
return null;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
if ($this->phpVersionProvider->isAtLeastPhpVersion(\Rector\Core\ValueObject\PhpVersion::PHP_74)) {
if ($propertyType instanceof \PHPStan\Type\UnionType) {
$this->propertyTypeDecorator->decoratePropertyUnionType($propertyType, $typeNode, $node, $phpDocInfo);
return $node;
}
$node->type = $typeNode;
return $node;
}
$this->phpDocTypeChanger->changeVarType($phpDocInfo, $propertyType);
return $node;
}
}

View File

@ -12,9 +12,9 @@ use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Doctrine\PhpDoc\ShortClassExpander;
use Rector\StaticTypeMapper\Naming\NameScopeFactory;
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
use Rector\TypeDeclaration\PhpDoc\ShortClassExpander;
final class CollectionTypeResolver
{
/**
@ -26,10 +26,10 @@ final class CollectionTypeResolver
*/
private $phpDocInfoFactory;
/**
* @var \Rector\TypeDeclaration\PhpDoc\ShortClassExpander
* @var \Rector\Doctrine\PhpDoc\ShortClassExpander
*/
private $shortClassExpander;
public function __construct(\Rector\StaticTypeMapper\Naming\NameScopeFactory $nameScopeFactory, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\TypeDeclaration\PhpDoc\ShortClassExpander $shortClassExpander)
public function __construct(\Rector\StaticTypeMapper\Naming\NameScopeFactory $nameScopeFactory, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \Rector\Doctrine\PhpDoc\ShortClassExpander $shortClassExpander)
{
$this->nameScopeFactory = $nameScopeFactory;
$this->phpDocInfoFactory = $phpDocInfoFactory;

View File

@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php';
if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) {
spl_autoload_call('RectorPrefix20211215\AutoloadIncluder');
}
if (!class_exists('ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061', false) && !interface_exists('ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061', false) && !trait_exists('ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061', false)) {
spl_autoload_call('RectorPrefix20211215\ComposerAutoloaderInitf98a46415524cbcbf0a0503e7dd3f061');
if (!class_exists('ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c', false) && !interface_exists('ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c', false) && !trait_exists('ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c', false)) {
spl_autoload_call('RectorPrefix20211215\ComposerAutoloaderInit179611c6f2ea972f3669c2fd86d0857c');
}
if (!class_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !interface_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !trait_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false)) {
spl_autoload_call('RectorPrefix20211215\Helmich\TypoScriptParser\Parser\AST\Statement');
@ -78,9 +78,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20211215\print_node(...func_get_args());
}
}
if (!function_exists('composerRequiref98a46415524cbcbf0a0503e7dd3f061')) {
function composerRequiref98a46415524cbcbf0a0503e7dd3f061() {
return \RectorPrefix20211215\composerRequiref98a46415524cbcbf0a0503e7dd3f061(...func_get_args());
if (!function_exists('composerRequire179611c6f2ea972f3669c2fd86d0857c')) {
function composerRequire179611c6f2ea972f3669c2fd86d0857c() {
return \RectorPrefix20211215\composerRequire179611c6f2ea972f3669c2fd86d0857c(...func_get_args());
}
}
if (!function_exists('scanPath')) {