Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -298,16 +298,12 @@ parameters:
- '#Class cognitive complexity for "DumpNodesCommand" is 103, keep it under 50#'
- '#Cognitive complexity for "Rector\\Utils\\DocumentationGenerator\\Command\\DumpNodesCommand\:\:execute\(\)" is \d+, keep it under 9#'

# just for utils
- '#Class "Rector\\Utils\\DoctrineAnnotationParserSyncer\\Rector\\(.*?)" is missing @see annotation with test case class reference#'

- '#Method Rector\\Utils\\DocumentationGenerator\\Node\\NodeClassProvider\:\:getNodeClasses\(\) should return array<class\-string\> but returns array<int, \(int\|string\)\>#'

- '#Parameter \#1 \$node of method Rector\\PostRector\\Collector\\NodesToAddCollector\:\:wrapToExpression\(\) expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Stmt, PhpParser\\Node given#'
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$class#'
- '#Method Rector\\BetterPhpDocParser\\Tests\\PhpDocParser\\AbstractPhpDocInfoTest\:\:parseFileAndGetFirstNodeOfType\(\) should return PhpParser\\Node but returns PhpParser\\Node\|null#'
- '#Method Rector\\Core\\Testing\\Finder\\RectorsFinder\:\:findInDirectories\(\) should return array<Rector\\Core\\Contract\\Rector\\RectorInterface\> but returns array<object\>#'
- '#Property PhpParser\\Node\\Stmt\\Namespace_\:\:\$stmts \(array<PhpParser\\Node\\Stmt\>\) does not accept array<PhpParser\\Node\>#'
- '#Call to function method_exists\(\) with \$this\(Rector\\PSR4\\Tests\\Rector\\MultipleClassFileToPsr4ClassesRector\\MultipleClassFileToPsr4ClassesRectorTest\) (.*?) will always evaluate to false#'

- '#Cognitive complexity for "Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier\:\:matchShortenedObjectType\(\)" is 10, keep it under 9#'
151 changes: 151 additions & 0 deletions rules/solid/src/NodeRemover/ClassMethodNodeRemover.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

declare(strict_types=1);

namespace Rector\SOLID\NodeRemover;

use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\PhpParser\NodeTraverser\CallableNodeTraverser;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\PostRector\Collector\NodesToRemoveCollector;

final class ClassMethodNodeRemover
{
/**
* @var NodesToRemoveCollector
*/
private $nodesToRemoveCollector;

/**
* @var NodeNameResolver
*/
private $nodeNameResolver;

/**
* @var CallableNodeTraverser
*/
private $callableNodeTraverser;

public function __construct(
NodesToRemoveCollector $nodesToRemoveCollector,
NodeNameResolver $nodeNameResolver,
CallableNodeTraverser $callableNodeTraverser
) {
$this->nodesToRemoveCollector = $nodesToRemoveCollector;
$this->nodeNameResolver = $nodeNameResolver;
$this->callableNodeTraverser = $callableNodeTraverser;
}

public function removeClassMethodIfUseless(ClassMethod $classMethod): void
{
if (count((array) $classMethod->params) > 0) {
return;
}

if (count((array) $classMethod->stmts) > 0) {
return;
}

$this->nodesToRemoveCollector->addNodeToRemove($classMethod);
}

public function removeParamFromMethodBody(ClassMethod $classMethod, Param $param): void
{
/** @var string $paramName */
$paramName = $this->nodeNameResolver->getName($param->var);

$this->callableNodeTraverser->traverseNodesWithCallable((array) $classMethod->stmts, function (Node $node) use (
$paramName
) {
if (! $this->isParentConstructStaticCall($node)) {
return null;
}

/** @var StaticCall $node */
$this->removeParamFromArgs($node, $paramName);

if (count($node->args) === 0) {
$this->nodesToRemoveCollector->addNodeToRemove($node);
}

return null;
});

foreach ((array) $classMethod->stmts as $key => $stmt) {
if ($stmt instanceof Expression) {
$stmt = $stmt->expr;
}

if (! $this->isParentConstructStaticCall($stmt)) {
continue;
}

/** @var StaticCall $stmt */
if (count($stmt->args) > 0) {
continue;
}

unset($classMethod->stmts[$key]);
}

$this->removeParamFromAssign($classMethod, $paramName);
}

private function removeParamFromArgs(StaticCall $staticCall, string $paramName): void
{
foreach ($staticCall->args as $key => $arg) {
if (! $this->nodeNameResolver->isName($arg->value, $paramName)) {
continue;
}

unset($staticCall->args[$key]);
}
}

private function removeParamFromAssign(ClassMethod $classMethod, string $paramName): void
{
foreach ((array) $classMethod->stmts as $key => $stmt) {
if ($stmt instanceof Expression) {
$stmt = $stmt->expr;
}

if (! $stmt instanceof Assign) {
continue;
}

if (! $stmt->expr instanceof Variable) {
continue;
}

if (! $this->nodeNameResolver->isName($stmt->expr, $paramName)) {
continue;
}

unset($classMethod->stmts[$key]);
}
}

private function isStaticCallNamed(Node $node, string $class, string $method): bool
{
if (! $node instanceof StaticCall) {
return false;
}

if (! $this->nodeNameResolver->isName($node->class, $class)) {
return false;
}

return $this->nodeNameResolver->isName($node->name, $method);
}

private function isParentConstructStaticCall(Node $node): bool
{
return $this->isStaticCallNamed($node, 'parent', '__construct');
}
}
Loading