diff --git a/rules/Php81/NodeManipulator/AttributeGroupNewLiner.php b/rules/Php81/NodeManipulator/AttributeGroupNewLiner.php new file mode 100644 index 00000000000..17b5c307d67 --- /dev/null +++ b/rules/Php81/NodeManipulator/AttributeGroupNewLiner.php @@ -0,0 +1,49 @@ +getOldTokens(); + $startTokenPos = $node->getStartTokenPos(); + if (!isset($oldTokens[$startTokenPos])) { + return; + } + if ($oldTokens[$startTokenPos]->text !== '#[') { + return; + } + $iteration = 1; + $lastKey = \array_key_last($node->attrGroups); + if ($lastKey === null) { + return; + } + $lastAttributeTokenPos = $node->attrGroups[$lastKey]->getEndTokenPos(); + while (isset($oldTokens[$startTokenPos + $iteration])) { + if ($startTokenPos + $iteration === $lastAttributeTokenPos) { + if ($oldTokens[$startTokenPos + $iteration]->text !== ']') { + break; + } + if (\trim($oldTokens[$startTokenPos + $iteration + 1]->text ?? '') === '') { + $space = \ltrim($oldTokens[$startTokenPos + $iteration + 1]->text ?? '', "\r\n"); + } elseif (\trim($oldTokens[$startTokenPos - 1]->text ?? '') === '') { + $space = \ltrim($oldTokens[$startTokenPos - 1]->text ?? '', "\r\n"); + } else { + $space = ''; + } + $oldTokens[$startTokenPos + $iteration]->text = "]\n" . $space; + break; + } + ++$iteration; + } + } +} diff --git a/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php b/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php index 3a93aecf87c..27ddbb4f408 100644 --- a/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php +++ b/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php @@ -22,7 +22,7 @@ use Rector\Comments\NodeDocBlock\DocBlockUpdater; use Rector\NodeAnalyzer\ParamAnalyzer; use Rector\NodeManipulator\PropertyFetchAssignManipulator; use Rector\NodeManipulator\PropertyManipulator; -use Rector\NodeTypeResolver\Node\AttributeKey; +use Rector\Php81\NodeManipulator\AttributeGroupNewLiner; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\PHPStan\ScopeFetcher; use Rector\Privatization\NodeManipulator\VisibilityManipulator; @@ -66,7 +66,11 @@ final class ReadOnlyPropertyRector extends AbstractRector implements MinPhpVersi * @readonly */ private DocBlockUpdater $docBlockUpdater; - public function __construct(PropertyManipulator $propertyManipulator, PropertyFetchAssignManipulator $propertyFetchAssignManipulator, ParamAnalyzer $paramAnalyzer, VisibilityManipulator $visibilityManipulator, BetterNodeFinder $betterNodeFinder, PhpDocInfoFactory $phpDocInfoFactory, DocBlockUpdater $docBlockUpdater) + /** + * @readonly + */ + private AttributeGroupNewLiner $attributeGroupNewLiner; + public function __construct(PropertyManipulator $propertyManipulator, PropertyFetchAssignManipulator $propertyFetchAssignManipulator, ParamAnalyzer $paramAnalyzer, VisibilityManipulator $visibilityManipulator, BetterNodeFinder $betterNodeFinder, PhpDocInfoFactory $phpDocInfoFactory, DocBlockUpdater $docBlockUpdater, AttributeGroupNewLiner $attributeGroupNewLiner) { $this->propertyManipulator = $propertyManipulator; $this->propertyFetchAssignManipulator = $propertyFetchAssignManipulator; @@ -75,6 +79,7 @@ final class ReadOnlyPropertyRector extends AbstractRector implements MinPhpVersi $this->betterNodeFinder = $betterNodeFinder; $this->phpDocInfoFactory = $phpDocInfoFactory; $this->docBlockUpdater = $docBlockUpdater; + $this->attributeGroupNewLiner = $attributeGroupNewLiner; } public function getRuleDefinition() : RuleDefinition { @@ -177,7 +182,7 @@ CODE_SAMPLE $this->visibilityManipulator->makeReadonly($property); $attributeGroups = $property->attrGroups; if ($attributeGroups !== []) { - $property->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $property); } $this->removeReadOnlyDoc($property); return $property; @@ -226,7 +231,7 @@ CODE_SAMPLE return null; } if ($param->attrGroups !== []) { - $param->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $param); } $this->visibilityManipulator->makeReadonly($param); $this->removeReadOnlyDoc($param); diff --git a/rules/Php82/Rector/Class_/ReadOnlyClassRector.php b/rules/Php82/Rector/Class_/ReadOnlyClassRector.php index e30393ca3e7..9b11f854bb1 100644 --- a/rules/Php82/Rector/Class_/ReadOnlyClassRector.php +++ b/rules/Php82/Rector/Class_/ReadOnlyClassRector.php @@ -14,9 +14,9 @@ use PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProvider; use Rector\NodeAnalyzer\ClassAnalyzer; -use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; use Rector\Php81\Enum\AttributeName; +use Rector\Php81\NodeManipulator\AttributeGroupNewLiner; use Rector\PHPStan\ScopeFetcher; use Rector\Privatization\NodeManipulator\VisibilityManipulator; use Rector\Rector\AbstractRector; @@ -47,12 +47,17 @@ final class ReadOnlyClassRector extends AbstractRector implements MinPhpVersionI * @readonly */ private ReflectionProvider $reflectionProvider; - public function __construct(ClassAnalyzer $classAnalyzer, VisibilityManipulator $visibilityManipulator, PhpAttributeAnalyzer $phpAttributeAnalyzer, ReflectionProvider $reflectionProvider) + /** + * @readonly + */ + private AttributeGroupNewLiner $attributeGroupNewLiner; + public function __construct(ClassAnalyzer $classAnalyzer, VisibilityManipulator $visibilityManipulator, PhpAttributeAnalyzer $phpAttributeAnalyzer, ReflectionProvider $reflectionProvider, AttributeGroupNewLiner $attributeGroupNewLiner) { $this->classAnalyzer = $classAnalyzer; $this->visibilityManipulator = $visibilityManipulator; $this->phpAttributeAnalyzer = $phpAttributeAnalyzer; $this->reflectionProvider = $reflectionProvider; + $this->attributeGroupNewLiner = $attributeGroupNewLiner; } public function getRuleDefinition() : RuleDefinition { @@ -98,21 +103,18 @@ CODE_SAMPLE foreach ($constructClassMethod->getParams() as $param) { $this->visibilityManipulator->removeReadonly($param); if ($param->attrGroups !== []) { - // invoke reprint with correct newline - $param->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $param); } } } foreach ($node->getProperties() as $property) { $this->visibilityManipulator->removeReadonly($property); if ($property->attrGroups !== []) { - // invoke reprint with correct newline - $property->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $property); } } if ($node->attrGroups !== []) { - // invoke reprint with correct readonly newline - $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $node); } return $node; } diff --git a/rules/Privatization/Rector/Class_/FinalizeTestCaseClassRector.php b/rules/Privatization/Rector/Class_/FinalizeTestCaseClassRector.php index 228c397fd6b..afbd4876ad8 100644 --- a/rules/Privatization/Rector/Class_/FinalizeTestCaseClassRector.php +++ b/rules/Privatization/Rector/Class_/FinalizeTestCaseClassRector.php @@ -6,7 +6,7 @@ namespace Rector\Privatization\Rector\Class_; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PHPStan\Reflection\ReflectionProvider; -use Rector\NodeTypeResolver\Node\AttributeKey; +use Rector\Php81\NodeManipulator\AttributeGroupNewLiner; use Rector\Privatization\NodeManipulator\VisibilityManipulator; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -24,10 +24,15 @@ final class FinalizeTestCaseClassRector extends AbstractRector * @readonly */ private VisibilityManipulator $visibilityManipulator; - public function __construct(ReflectionProvider $reflectionProvider, VisibilityManipulator $visibilityManipulator) + /** + * @readonly + */ + private AttributeGroupNewLiner $attributeGroupNewLiner; + public function __construct(ReflectionProvider $reflectionProvider, VisibilityManipulator $visibilityManipulator, AttributeGroupNewLiner $attributeGroupNewLiner) { $this->reflectionProvider = $reflectionProvider; $this->visibilityManipulator = $visibilityManipulator; + $this->attributeGroupNewLiner = $attributeGroupNewLiner; } public function getRuleDefinition() : RuleDefinition { @@ -78,7 +83,7 @@ CODE_SAMPLE return null; } if ($node->attrGroups !== []) { - $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); + $this->attributeGroupNewLiner->newLine($this->file, $node); } $this->visibilityManipulator->makeFinal($node); return $node; diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index fe5113f0917..635e11427a9 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '8fea0f5b27dbdb4d3e0b2d672d43c60cb0c2ea2c'; + public const PACKAGE_VERSION = '6aca457745976acad6cec231ffc400f0d399a386'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-12-19 08:35:14'; + public const RELEASE_DATE = '2024-12-19 15:58:19'; /** * @var int */ diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index d90e5082e34..704f9c9a094 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -1995,6 +1995,7 @@ return array( 'Rector\\Php81\\NodeAnalyzer\\CoalesePropertyAssignMatcher' => $baseDir . '/rules/Php81/NodeAnalyzer/CoalesePropertyAssignMatcher.php', 'Rector\\Php81\\NodeAnalyzer\\ComplexNewAnalyzer' => $baseDir . '/rules/Php81/NodeAnalyzer/ComplexNewAnalyzer.php', 'Rector\\Php81\\NodeFactory\\EnumFactory' => $baseDir . '/rules/Php81/NodeFactory/EnumFactory.php', + 'Rector\\Php81\\NodeManipulator\\AttributeGroupNewLiner' => $baseDir . '/rules/Php81/NodeManipulator/AttributeGroupNewLiner.php', 'Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector' => $baseDir . '/rules/Php81/Rector/Array_/FirstClassCallableRector.php', 'Rector\\Php81\\Rector\\ClassMethod\\NewInInitializerRector' => $baseDir . '/rules/Php81/Rector/ClassMethod/NewInInitializerRector.php', 'Rector\\Php81\\Rector\\Class_\\MyCLabsClassToEnumRector' => $baseDir . '/rules/Php81/Rector/Class_/MyCLabsClassToEnumRector.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 17698aa90d3..8cdb15547ec 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -2214,6 +2214,7 @@ class ComposerStaticInite1459f150f08d0eee2804dfc37f818db 'Rector\\Php81\\NodeAnalyzer\\CoalesePropertyAssignMatcher' => __DIR__ . '/../..' . '/rules/Php81/NodeAnalyzer/CoalesePropertyAssignMatcher.php', 'Rector\\Php81\\NodeAnalyzer\\ComplexNewAnalyzer' => __DIR__ . '/../..' . '/rules/Php81/NodeAnalyzer/ComplexNewAnalyzer.php', 'Rector\\Php81\\NodeFactory\\EnumFactory' => __DIR__ . '/../..' . '/rules/Php81/NodeFactory/EnumFactory.php', + 'Rector\\Php81\\NodeManipulator\\AttributeGroupNewLiner' => __DIR__ . '/../..' . '/rules/Php81/NodeManipulator/AttributeGroupNewLiner.php', 'Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/Array_/FirstClassCallableRector.php', 'Rector\\Php81\\Rector\\ClassMethod\\NewInInitializerRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/ClassMethod/NewInInitializerRector.php', 'Rector\\Php81\\Rector\\Class_\\MyCLabsClassToEnumRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/Class_/MyCLabsClassToEnumRector.php',