diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 0d9e64d2575..9852f490cda 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 = '1b1807b0f8426641e13e5914389e1c118b3a3d14'; + public const PACKAGE_VERSION = '2c6790841ec149b1849c5b931b7b46648fe2f18e'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-11-08 17:26:04'; + public const RELEASE_DATE = '2024-11-08 14:55:18'; /** * @var int */ diff --git a/src/NodeManipulator/ClassDependencyManipulator.php b/src/NodeManipulator/ClassDependencyManipulator.php index 3e24022e969..0aaaa401af8 100644 --- a/src/NodeManipulator/ClassDependencyManipulator.php +++ b/src/NodeManipulator/ClassDependencyManipulator.php @@ -23,6 +23,9 @@ use Rector\TypeDeclaration\NodeAnalyzer\AutowiredClassMethodOrPropertyAnalyzer; use Rector\ValueObject\MethodName; use Rector\ValueObject\PhpVersionFeature; +/** + * @see \Rector\Tests\NodeManipulator\ClassDependencyManipulatorTest + */ final class ClassDependencyManipulator { /** diff --git a/src/NodeManipulator/ClassInsertManipulator.php b/src/NodeManipulator/ClassInsertManipulator.php index ed48b4296a1..c669096d350 100644 --- a/src/NodeManipulator/ClassInsertManipulator.php +++ b/src/NodeManipulator/ClassInsertManipulator.php @@ -3,7 +3,6 @@ declare (strict_types=1); namespace Rector\NodeManipulator; -use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassConst; use PhpParser\Node\Stmt\ClassMethod; @@ -24,19 +23,47 @@ public function __construct(NodeFactory $nodeFactory) } /** * @api - * @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\ClassMethod $stmt + * @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\ClassMethod $addedStmt */ - public function addAsFirstMethod(Class_ $class, $stmt) : void + public function addAsFirstMethod(Class_ $class, $addedStmt) : void { $scope = $class->getAttribute(AttributeKey::SCOPE); - $stmt->setAttribute(AttributeKey::SCOPE, $scope); - if ($this->isSuccessToInsertBeforeFirstMethod($class, $stmt)) { + $addedStmt->setAttribute(AttributeKey::SCOPE, $scope); + // no stmts? add this one + if ($class->stmts === []) { + $class->stmts[] = $addedStmt; return; } - if ($this->isSuccessToInsertAfterLastProperty($class, $stmt)) { + $newClassStmts = []; + $isAdded = \false; + foreach ($class->stmts as $key => $classStmt) { + $nextStmt = $class->stmts[$key + 1] ?? null; + if ($isAdded === \false) { + // first class method + if ($classStmt instanceof ClassMethod) { + $newClassStmts[] = $addedStmt; + $newClassStmts[] = $classStmt; + $isAdded = \true; + continue; + } + // after last property + if ($classStmt instanceof Property && !$nextStmt instanceof Property) { + $newClassStmts[] = $classStmt; + $newClassStmts[] = $addedStmt; + $isAdded = \true; + continue; + } + } + $newClassStmts[] = $classStmt; + } + // still not added? try after last trait + // @todo + if ($isAdded) { + $class->stmts = $newClassStmts; return; } - $class->stmts[] = $stmt; + // keep added at least as first stmt + $class->stmts = \array_merge([$addedStmt], $class->stmts); } /** * @internal Use PropertyAdder service instead @@ -50,42 +77,4 @@ public function addPropertyToClass(Class_ $class, string $name, ?Type $type) : v $property = $this->nodeFactory->createPrivatePropertyFromNameAndType($name, $type); $this->addAsFirstMethod($class, $property); } - /** - * @param Stmt[] $stmts - * @return Stmt[] - */ - private function insertBefore(array $stmts, Stmt $stmt, int $key) : array - { - \array_splice($stmts, $key, 0, [$stmt]); - return $stmts; - } - /** - * @param \PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property $stmt - */ - private function isSuccessToInsertBeforeFirstMethod(Class_ $class, $stmt) : bool - { - foreach ($class->stmts as $key => $classStmt) { - if (!$classStmt instanceof ClassMethod) { - continue; - } - $class->stmts = $this->insertBefore($class->stmts, $stmt, $key); - return \true; - } - return \false; - } - /** - * @param \PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property $stmt - */ - private function isSuccessToInsertAfterLastProperty(Class_ $class, $stmt) : bool - { - $previousElement = null; - foreach ($class->stmts as $key => $classStmt) { - if ($previousElement instanceof Property && !$classStmt instanceof Property) { - $class->stmts = $this->insertBefore($class->stmts, $stmt, $key); - return \true; - } - $previousElement = $classStmt; - } - return \false; - } }