From 82687502deb9d41ed79ed832baa09fe23f90d3f8 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 9 Jun 2023 01:01:25 +0200 Subject: [PATCH] Avoid parent node lookup in RemoveEmptyClassMethodRector (#4129) --- .../Rector/New_/NewStaticToNewSelfRector.php | 38 ++++++++----- .../RemoveEmptyClassMethodRector.php | 53 +++++++++++-------- .../StaticToSelfOnFinalClassRector.php | 44 +++++++-------- 3 files changed, 77 insertions(+), 58 deletions(-) diff --git a/rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.php b/rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.php index b7dd01af036..a7200f44aa1 100644 --- a/rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.php +++ b/rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.php @@ -25,7 +25,7 @@ public function getRuleDefinition(): RuleDefinition return new RuleDefinition('Change unsafe new static() to new self()', [ new CodeSample( <<<'CODE_SAMPLE' -class SomeClass +final class SomeClass { public function build() { @@ -36,7 +36,7 @@ public function build() , <<<'CODE_SAMPLE' -class SomeClass +final class SomeClass { public function build() { @@ -53,29 +53,39 @@ public function build() */ public function getNodeTypes(): array { - return [New_::class]; + return [Class_::class]; } /** - * @param New_ $node + * @param Class_ $node */ public function refactor(Node $node): ?Node { - $class = $this->betterNodeFinder->findParentType($node, Class_::class); - if (! $class instanceof Class_) { + if (! $node->isFinal()) { return null; } - if (! $class->isFinal()) { - return null; - } + $hasChanged = false; - if (! $this->isName($node->class, ObjectReference::STATIC)) { - return null; - } + $this->traverseNodesWithCallable($node, function (Node $node) use (&$hasChanged): ?New_ { + if (! $node instanceof New_) { + return null; + } - $node->class = new Name(ObjectReference::SELF); + if (! $this->isName($node->class, ObjectReference::STATIC)) { + return null; + } + + $hasChanged = true; + + $node->class = new Name(ObjectReference::SELF); + return $node; + }); + + if ($hasChanged) { + return $node; + } - return $node; + return null; } } diff --git a/rules/DeadCode/Rector/ClassMethod/RemoveEmptyClassMethodRector.php b/rules/DeadCode/Rector/ClassMethod/RemoveEmptyClassMethodRector.php index 0e3b9260395..f2a479f519b 100644 --- a/rules/DeadCode/Rector/ClassMethod/RemoveEmptyClassMethodRector.php +++ b/rules/DeadCode/Rector/ClassMethod/RemoveEmptyClassMethodRector.php @@ -8,7 +8,6 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\NodeTraverser; use Rector\Core\NodeAnalyzer\ParamAnalyzer; use Rector\Core\NodeManipulator\ClassMethodManipulator; use Rector\Core\Rector\AbstractRector; @@ -59,40 +58,50 @@ class OrphanClass */ public function getNodeTypes(): array { - return [ClassMethod::class]; + return [Class_::class]; } /** - * @param ClassMethod $node + * @param Class_ $node */ - public function refactor(Node $node): ?int + public function refactor(Node $node): ?Class_ { - $classLike = $this->betterNodeFinder->findParentType($node, Class_::class); - if (! $classLike instanceof Class_) { - return null; - } + $hasChanged = false; - if ($node->stmts !== null && $node->stmts !== []) { - return null; - } + foreach ($node->stmts as $key => $stmt) { + if (! $stmt instanceof ClassMethod) { + continue; + } - if ($node->isAbstract()) { - return null; - } + if ($stmt->stmts !== null && $stmt->stmts !== []) { + continue; + } - if ($node->isFinal() && ! $classLike->isFinal()) { - return null; - } + if ($stmt->isAbstract()) { + continue; + } + + if ($stmt->isFinal() && ! $node->isFinal()) { + continue; + } + + if ($this->shouldSkipNonFinalNonPrivateClassMethod($node, $stmt)) { + continue; + } + + if ($this->shouldSkipClassMethod($node, $stmt)) { + continue; + } - if ($this->shouldSkipNonFinalNonPrivateClassMethod($classLike, $node)) { - return null; + unset($node->stmts[$key]); + $hasChanged = true; } - if ($this->shouldSkipClassMethod($classLike, $node)) { - return null; + if ($hasChanged) { + return $node; } - return NodeTraverser::REMOVE_NODE; + return null; } private function shouldSkipNonFinalNonPrivateClassMethod(Class_ $class, ClassMethod $classMethod): bool diff --git a/rules/Php55/Rector/ClassConstFetch/StaticToSelfOnFinalClassRector.php b/rules/Php55/Rector/ClassConstFetch/StaticToSelfOnFinalClassRector.php index 3f79beb5ffb..f2e0460c63d 100644 --- a/rules/Php55/Rector/ClassConstFetch/StaticToSelfOnFinalClassRector.php +++ b/rules/Php55/Rector/ClassConstFetch/StaticToSelfOnFinalClassRector.php @@ -6,8 +6,6 @@ use PhpParser\Node; use PhpParser\Node\Expr\ClassConstFetch; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; use Rector\Core\Enum\ObjectReference; use Rector\Core\Rector\AbstractRector; @@ -55,40 +53,42 @@ public function callOnMe() */ public function getNodeTypes(): array { - return [ClassConstFetch::class]; + return [Class_::class]; } /** - * @param ClassConstFetch $node + * @param Class_ $node */ - public function refactor(Node $node): ?ClassConstFetch + public function refactor(Node $node): ?Class_ { - if (! $node->class instanceof Name) { + if (! $node->isFinal()) { return null; } - if (! $node->name instanceof Identifier) { - return null; - } + $hasChanged = false; - if ($node->class->toString() !== ObjectReference::STATIC) { - return null; - } + $this->traverseNodesWithCallable($node, function (Node $node) use (&$hasChanged): ?ClassConstFetch { + if (! $node instanceof ClassConstFetch) { + return null; + } - if ($node->name->toString() !== 'class') { - return null; - } + if (! $this->isName($node->class, ObjectReference::STATIC)) { + return null; + } - $class = $this->betterNodeFinder->findParentType($node, Class_::class); - if (! $class instanceof Class_) { - return null; - } + if (! $this->isName($node->name, 'class')) { + return null; + } - if (! $class->isFinal()) { - return null; + $hasChanged = true; + return $this->nodeFactory->createSelfFetchConstant('class'); + }); + + if ($hasChanged) { + return $node; } - return $this->nodeFactory->createSelfFetchConstant('class'); + return null; } public function provideMinPhpVersion(): int