Updated Rector to commit 106bc8ed2efbf98e99c22d6098a78ec2d6588c58

106bc8ed2e Remove AttributeCompatibleAnnotationRector, as only for one-time migration of private project, not suitable for general use (#4064)
This commit is contained in:
Tomas Votruba 2023-06-04 17:52:08 +00:00
parent a21bcfc1f7
commit f0c9d40cc2
12 changed files with 16 additions and 391 deletions

View File

@ -1,4 +1,4 @@
# 390 Rules Overview
# 389 Rules Overview
<br>
@ -10,8 +10,6 @@
- [CodingStyle](#codingstyle) (34)
- [Compatibility](#compatibility) (1)
- [DeadCode](#deadcode) (46)
- [DependencyInjection](#dependencyinjection) (2)
@ -2502,39 +2500,6 @@ Wrap encapsed variables in curly braces
<br>
## Compatibility
### AttributeCompatibleAnnotationRector
Change annotation to attribute compatible form, see https://tomasvotruba.com/blog/doctrine-annotations-and-attributes-living-together-in-peace/
- class: [`Rector\Compatibility\Rector\Class_\AttributeCompatibleAnnotationRector`](../rules/Compatibility/Rector/Class_/AttributeCompatibleAnnotationRector.php)
```diff
-use Doctrine\Common\Annotations\Annotation\Required;
+use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
/**
* @annotation
+ * @NamedArgumentConstructor
*/
class SomeAnnotation
{
/**
- * @var string[]
- * @Required()
+ * @param string[] $enum
*/
- public array $enum;
+ public function __construct(
+ public array $enum
+ ) {
+ }
}
```
<br>
## DeadCode
### RecastingRemovalRector

View File

@ -236,6 +236,9 @@ final class PhpDocInfo
$doctrineAnnotationTagValueNodes = $this->phpDocNodeByTypeFinder->findDoctrineAnnotationsByClass($this->phpDocNode, $class);
return $doctrineAnnotationTagValueNodes[0] ?? null;
}
/**
* @api used in tests
*/
public function hasByAnnotationClass(string $class) : bool
{
return $this->findByAnnotationClass($class) !== [];

View File

@ -54,16 +54,6 @@ final class AttributeKey
* @var string
*/
public const ORIGINAL_NAME = 'originalName';
/**
* @api
* @deprecated Use $node->namespacedName instead
*
* Internal php-parser name. @see \PhpParser\NodeVisitor\NameResolver
* Do not change this even if you want!
*
* @var string
*/
public const RESOLVED_NAME = 'resolvedName';
/**
* @deprecated Refactor to a custom visitors/parent node instead,
* @see https://phpstan.org/blog/preprocessing-ast-for-custom-rules
@ -73,24 +63,6 @@ final class AttributeKey
* @var string
*/
public const PARENT_NODE = 'parent';
/**
* @api
* @internal of php-parser, do not change
* @deprecated Use StmtsAwareInterface instead
*
* @see https://github.com/nikic/PHP-Parser/pull/681/files
* @var string
*/
public const PREVIOUS_NODE = 'previous';
/**
* @api
* @internal of php-parser, do not change
* @deprecated Use StmtsAwareInterface instead
*
* @see https://github.com/nikic/PHP-Parser/pull/681/files
* @var string
*/
public const NEXT_NODE = 'next';
/**
* Internal php-parser name.
* Do not change this even if you want!

View File

@ -1,47 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Compatibility\NodeAnalyzer;
use PhpParser\Node\Expr;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
final class RequiredAnnotationPropertyAnalyzer
{
/**
* @readonly
* @var \Rector\Core\PhpParser\Node\Value\ValueResolver
*/
private $valueResolver;
public function __construct(ValueResolver $valueResolver)
{
$this->valueResolver = $valueResolver;
}
public function isRequiredProperty(PhpDocInfo $phpDocInfo, Property $property) : bool
{
if ($phpDocInfo->hasByAnnotationClass('Doctrine\\Common\\Annotations\\Annotation\\Required')) {
return \true;
}
// sometimes property has default null, but @var says its not null - that's due to nullability of typed properties
// in that case, we should treat property as required
$firstProperty = $property->props[0];
if (!$firstProperty->default instanceof Expr) {
return \false;
}
if (!$this->valueResolver->isNull($firstProperty->default)) {
return \false;
}
$varTagValueNode = $phpDocInfo->getVarTagValueNode();
if (!$varTagValueNode instanceof VarTagValueNode) {
return \false;
}
if ($varTagValueNode->type instanceof NullableTypeNode) {
return \false;
}
return $property->type instanceof NullableType;
}
}

View File

@ -1,45 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Compatibility\NodeFactory;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Compatibility\ValueObject\PropertyWithPhpDocInfo;
use Rector\Core\ValueObject\MethodName;
use Rector\DeadCode\PhpDoc\TagRemover\ParamTagRemover;
final class ConstructorClassMethodFactory
{
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @readonly
* @var \Rector\DeadCode\PhpDoc\TagRemover\ParamTagRemover
*/
private $paramTagRemover;
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, ParamTagRemover $paramTagRemover)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->paramTagRemover = $paramTagRemover;
}
/**
* @param PropertyWithPhpDocInfo[] $requiredPropertiesWithPhpDocInfos
* @param Param[] $params
*/
public function createConstructorClassMethod(array $requiredPropertiesWithPhpDocInfos, array $params) : ClassMethod
{
$classMethod = new ClassMethod(MethodName::CONSTRUCT, ['flags' => Class_::MODIFIER_PUBLIC, 'params' => $params]);
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod);
foreach ($requiredPropertiesWithPhpDocInfos as $requiredPropertyWithPhpDocInfo) {
$paramTagValueNode = $requiredPropertyWithPhpDocInfo->getParamTagValueNode();
$phpDocInfo->addTagValueNode($paramTagValueNode);
}
$this->paramTagRemover->removeParamTagsIfUseless($phpDocInfo, $classMethod);
return $classMethod;
}
}

View File

@ -1,165 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Compatibility\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover;
use Rector\Compatibility\NodeAnalyzer\RequiredAnnotationPropertyAnalyzer;
use Rector\Compatibility\NodeFactory\ConstructorClassMethodFactory;
use Rector\Compatibility\ValueObject\PropertyWithPhpDocInfo;
use Rector\Core\Rector\AbstractRector;
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
use Rector\Php81\Enum\AttributeName;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Compatibility\Rector\Class_\AttributeCompatibleAnnotationRector\AttributeCompatibleAnnotationRectorTest
*/
final class AttributeCompatibleAnnotationRector extends AbstractRector
{
/**
* @readonly
* @var \Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer
*/
private $phpAttributeAnalyzer;
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover
*/
private $phpDocTagRemover;
/**
* @readonly
* @var \Rector\Compatibility\NodeAnalyzer\RequiredAnnotationPropertyAnalyzer
*/
private $requiredAnnotationPropertyAnalyzer;
/**
* @readonly
* @var \Rector\Compatibility\NodeFactory\ConstructorClassMethodFactory
*/
private $constructorClassMethodFactory;
public function __construct(PhpAttributeAnalyzer $phpAttributeAnalyzer, PhpDocTagRemover $phpDocTagRemover, RequiredAnnotationPropertyAnalyzer $requiredAnnotationPropertyAnalyzer, ConstructorClassMethodFactory $constructorClassMethodFactory)
{
$this->phpAttributeAnalyzer = $phpAttributeAnalyzer;
$this->phpDocTagRemover = $phpDocTagRemover;
$this->requiredAnnotationPropertyAnalyzer = $requiredAnnotationPropertyAnalyzer;
$this->constructorClassMethodFactory = $constructorClassMethodFactory;
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Change annotation to attribute compatible form, see https://tomasvotruba.com/blog/doctrine-annotations-and-attributes-living-together-in-peace/', [new CodeSample(<<<'CODE_SAMPLE'
use Doctrine\Common\Annotations\Annotation\Required;
/**
* @annotation
*/
class SomeAnnotation
{
/**
* @var string[]
* @Required()
*/
public array $enum;
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
/**
* @annotation
* @NamedArgumentConstructor
*/
class SomeAnnotation
{
/**
* @param string[] $enum
*/
public function __construct(
public array $enum
) {
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node) : ?Node
{
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
if (!$phpDocInfo instanceof PhpDocInfo) {
return null;
}
if ($this->shouldSkipClass($phpDocInfo, $node)) {
return null;
}
// add "NamedArgumentConstructor"
$phpDocInfo->addTagValueNode(new DoctrineAnnotationTagValueNode(new IdentifierTypeNode('Doctrine\\Common\\Annotations\\Annotation\\NamedArgumentConstructor')));
// resolve required properties
$requiredPropertiesWithPhpDocInfos = [];
foreach ($node->getProperties() as $property) {
if (!$property->isPublic()) {
continue;
}
$propertyPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
if (!$this->requiredAnnotationPropertyAnalyzer->isRequiredProperty($propertyPhpDocInfo, $property)) {
continue;
}
$propertyName = $this->getName($property);
$requiredPropertiesWithPhpDocInfos[] = new PropertyWithPhpDocInfo($propertyName, $property, $propertyPhpDocInfo);
}
$params = $this->createConstructParams($requiredPropertiesWithPhpDocInfos);
$constructorClassMethod = $this->constructorClassMethodFactory->createConstructorClassMethod($requiredPropertiesWithPhpDocInfos, $params);
$node->stmts = \array_merge($node->stmts, [$constructorClassMethod]);
return $node;
}
private function shouldSkipClass(PhpDocInfo $phpDocInfo, Class_ $class) : bool
{
if (!$phpDocInfo->hasByNames(['Annotation', 'annotation'])) {
return \true;
}
if ($phpDocInfo->hasByAnnotationClass('Doctrine\\Common\\Annotations\\Annotation\\NamedArgumentConstructor')) {
return \true;
}
// has attribute? skip it
return $this->phpAttributeAnalyzer->hasPhpAttribute($class, AttributeName::ATTRIBUTE);
}
/**
* @param PropertyWithPhpDocInfo[] $requiredPropertiesWithPhpDocInfos
* @return Param[]
*/
private function createConstructParams(array $requiredPropertiesWithPhpDocInfos) : array
{
$params = [];
foreach ($requiredPropertiesWithPhpDocInfos as $requiredPropertyWithPhpDocInfo) {
$property = $requiredPropertyWithPhpDocInfo->getProperty();
$propertyName = $this->getName($property);
// unwrap nullable type, as variable is required
$propertyType = $property->type;
if ($propertyType instanceof NullableType) {
$propertyType = $propertyType->type;
}
$params[] = new Param(new Variable($propertyName), null, $propertyType, \false, \false, [], $property->flags);
$propertyPhpDocInfo = $requiredPropertyWithPhpDocInfo->getPhpDocInfo();
// remove required
$this->phpDocTagRemover->removeByName($propertyPhpDocInfo, 'Doctrine\\Common\\Annotations\\Annotation\\Required');
$this->removeNode($property);
}
return $params;
}
}

View File

@ -1,50 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Compatibility\ValueObject;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Core\Exception\ShouldNotHappenException;
final class PropertyWithPhpDocInfo
{
/**
* @readonly
* @var string
*/
private $propertyName;
/**
* @readonly
* @var \PhpParser\Node\Stmt\Property
*/
private $property;
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo
*/
private $phpDocInfo;
public function __construct(string $propertyName, Property $property, PhpDocInfo $phpDocInfo)
{
$this->propertyName = $propertyName;
$this->property = $property;
$this->phpDocInfo = $phpDocInfo;
}
public function getProperty() : Property
{
return $this->property;
}
public function getPhpDocInfo() : PhpDocInfo
{
return $this->phpDocInfo;
}
public function getParamTagValueNode() : ParamTagValueNode
{
$varTagValueNode = $this->phpDocInfo->getVarTagValueNode();
if (!$varTagValueNode instanceof VarTagValueNode) {
throw new ShouldNotHappenException();
}
return new ParamTagValueNode($varTagValueNode->type, \false, '$' . $this->propertyName, '');
}
}

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '141923f2484a506bbd523021facb07d37575e62f';
public const PACKAGE_VERSION = '106bc8ed2efbf98e99c22d6098a78ec2d6588c58';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-06-04 17:36:49';
public const RELEASE_DATE = '2023-06-04 18:48:27';
/**
* @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 ComposerAutoloaderInit82ed4196913b5b07441c4b4a2e9a4b7c::getLoader();
return ComposerAutoloaderInit66e33d12c7cef6d358659906bd886349::getLoader();

View File

@ -1362,10 +1362,6 @@ return array(
'Rector\\Comments\\NodeDocBlock\\DocBlockUpdater' => $baseDir . '/packages/Comments/NodeDocBlock/DocBlockUpdater.php',
'Rector\\Comments\\NodeTraverser\\CommentRemovingNodeTraverser' => $baseDir . '/packages/Comments/NodeTraverser/CommentRemovingNodeTraverser.php',
'Rector\\Comments\\NodeVisitor\\CommentRemovingNodeVisitor' => $baseDir . '/packages/Comments/NodeVisitor/CommentRemovingNodeVisitor.php',
'Rector\\Compatibility\\NodeAnalyzer\\RequiredAnnotationPropertyAnalyzer' => $baseDir . '/rules/Compatibility/NodeAnalyzer/RequiredAnnotationPropertyAnalyzer.php',
'Rector\\Compatibility\\NodeFactory\\ConstructorClassMethodFactory' => $baseDir . '/rules/Compatibility/NodeFactory/ConstructorClassMethodFactory.php',
'Rector\\Compatibility\\Rector\\Class_\\AttributeCompatibleAnnotationRector' => $baseDir . '/rules/Compatibility/Rector/Class_/AttributeCompatibleAnnotationRector.php',
'Rector\\Compatibility\\ValueObject\\PropertyWithPhpDocInfo' => $baseDir . '/rules/Compatibility/ValueObject/PropertyWithPhpDocInfo.php',
'Rector\\Config\\RectorConfig' => $baseDir . '/packages/Config/RectorConfig.php',
'Rector\\Core\\Application\\ApplicationFileProcessor' => $baseDir . '/src/Application/ApplicationFileProcessor.php',
'Rector\\Core\\Application\\ChangedNodeScopeRefresher' => $baseDir . '/src/Application/ChangedNodeScopeRefresher.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit82ed4196913b5b07441c4b4a2e9a4b7c
class ComposerAutoloaderInit66e33d12c7cef6d358659906bd886349
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInit82ed4196913b5b07441c4b4a2e9a4b7c
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit82ed4196913b5b07441c4b4a2e9a4b7c', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit66e33d12c7cef6d358659906bd886349', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit82ed4196913b5b07441c4b4a2e9a4b7c', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit66e33d12c7cef6d358659906bd886349', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit66e33d12c7cef6d358659906bd886349::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit66e33d12c7cef6d358659906bd886349::$files;
$requireFile = \Closure::bind(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 ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c
class ComposerStaticInit66e33d12c7cef6d358659906bd886349
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -1604,10 +1604,6 @@ class ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c
'Rector\\Comments\\NodeDocBlock\\DocBlockUpdater' => __DIR__ . '/../..' . '/packages/Comments/NodeDocBlock/DocBlockUpdater.php',
'Rector\\Comments\\NodeTraverser\\CommentRemovingNodeTraverser' => __DIR__ . '/../..' . '/packages/Comments/NodeTraverser/CommentRemovingNodeTraverser.php',
'Rector\\Comments\\NodeVisitor\\CommentRemovingNodeVisitor' => __DIR__ . '/../..' . '/packages/Comments/NodeVisitor/CommentRemovingNodeVisitor.php',
'Rector\\Compatibility\\NodeAnalyzer\\RequiredAnnotationPropertyAnalyzer' => __DIR__ . '/../..' . '/rules/Compatibility/NodeAnalyzer/RequiredAnnotationPropertyAnalyzer.php',
'Rector\\Compatibility\\NodeFactory\\ConstructorClassMethodFactory' => __DIR__ . '/../..' . '/rules/Compatibility/NodeFactory/ConstructorClassMethodFactory.php',
'Rector\\Compatibility\\Rector\\Class_\\AttributeCompatibleAnnotationRector' => __DIR__ . '/../..' . '/rules/Compatibility/Rector/Class_/AttributeCompatibleAnnotationRector.php',
'Rector\\Compatibility\\ValueObject\\PropertyWithPhpDocInfo' => __DIR__ . '/../..' . '/rules/Compatibility/ValueObject/PropertyWithPhpDocInfo.php',
'Rector\\Config\\RectorConfig' => __DIR__ . '/../..' . '/packages/Config/RectorConfig.php',
'Rector\\Core\\Application\\ApplicationFileProcessor' => __DIR__ . '/../..' . '/src/Application/ApplicationFileProcessor.php',
'Rector\\Core\\Application\\ChangedNodeScopeRefresher' => __DIR__ . '/../..' . '/src/Application/ChangedNodeScopeRefresher.php',
@ -3060,9 +3056,9 @@ class ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit82ed4196913b5b07441c4b4a2e9a4b7c::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit66e33d12c7cef6d358659906bd886349::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit66e33d12c7cef6d358659906bd886349::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit66e33d12c7cef6d358659906bd886349::$classMap;
}, null, ClassLoader::class);
}