Skip to content

Commit

Permalink
Skip used in new ctor (#2425)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Jun 4, 2022
1 parent 283a9af commit c3581f9
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ public function __construct(
) {
}

public function replaceTagByAnother(PhpDocInfo $phpDocInfo, string $oldTag, string $newTag): void
public function replaceTagByAnother(PhpDocInfo $phpDocInfo, string $oldTag, string $newTag): bool
{
$hasChanged = false;

$oldTag = $this->annotationNaming->normalizeName($oldTag);
$newTag = $this->annotationNaming->normalizeName($newTag);

Expand All @@ -33,6 +35,9 @@ public function replaceTagByAnother(PhpDocInfo $phpDocInfo, string $oldTag, stri

unset($phpDocNode->children[$key]);
$phpDocNode->children[] = new PhpDocTagNode($newTag, new GenericTagValueNode(''));
$hasChanged = true;
}

return $hasChanged;
}
}
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -717,3 +717,5 @@ parameters:
-
message: '#Offset \d+ does not exist on array<PhpParser\\Node\\Stmt>\|null#'
path: rules/DeadCode/Rector/StmtsAwareInterface/RemoveJustPropertyFetchForAssignRector.php

- '#Method "replaceTagByAnother\(\)" returns bool type, so the name should start with is/has/was#'
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class RemoveLast
{
private function run(string $used, int $notUsed)
Expand All @@ -12,6 +14,8 @@ final class RemoveLast
-----
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class RemoveLast
{
private function run(string $used)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUnusedPrivateMethodParameterRector\Fixture;

final class SkipAnonymousClassConstructor
{
public function start()
{
$this->run(5);
$this->run();
}

private function run($value = 100)
{
$class = new class($value) {
private $value;

public function __construct($value)
{
$this->value = $value;
}
};
}
}
7 changes: 5 additions & 2 deletions rules/Renaming/Rector/ClassMethod/RenameAnnotationRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,15 @@ public function refactor(Node $node): ?Node
continue;
}

$this->docBlockTagReplacer->replaceTagByAnother(
$hasDocBlockChanged = $this->docBlockTagReplacer->replaceTagByAnother(
$phpDocInfo,
$renameAnnotation->getOldAnnotation(),
$renameAnnotation->getNewAnnotation()
);
$hasChanged = true;

if ($hasDocBlockChanged) {
$hasChanged = true;
}
}

if (! $hasChanged) {
Expand Down
71 changes: 56 additions & 15 deletions src/NodeAnalyzer/ParamAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,68 @@
namespace Rector\Core\NodeAnalyzer;

use PhpParser\Node;
use PhpParser\Node\Expr\CallLike;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use Rector\Core\NodeManipulator\FuncCallManipulator;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Value\ValueResolver;
use Rector\NodeNameResolver\NodeNameResolver;
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;

final class ParamAnalyzer
{
public function __construct(
private readonly BetterNodeFinder $betterNodeFinder,
private readonly NodeComparator $nodeComparator,
private readonly ValueResolver $valueResolver,
private readonly NodeNameResolver $nodeNameResolver,
private readonly FuncCallManipulator $funcCallManipulator
private readonly FuncCallManipulator $funcCallManipulator,
private readonly SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
) {
}

public function isParamUsedInClassMethod(ClassMethod $classMethod, Param $param): bool
{
return (bool) $this->betterNodeFinder->findFirstInFunctionLikeScoped($classMethod, function (Node $node) use (
$isParamUsed = false;

$this->simpleCallableNodeTraverser->traverseNodesWithCallable($classMethod->stmts, function (Node $node) use (
&$isParamUsed,
$param
): bool {
if (! $node instanceof Variable && ! $node instanceof Closure && ! $node instanceof FuncCall) {
return false;
): ?int {
if ($this->isUsedAsArg($node, $param)) {
$isParamUsed = true;
}

// skip nested anonymous class
if ($node instanceof Class_ || $node instanceof Function_) {
return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
}

if ($node instanceof Variable) {
return $this->nodeComparator->areNodesEqual($node, $param->var);
if ($node instanceof Variable && $this->nodeComparator->areNodesEqual($node, $param->var)) {
$isParamUsed = true;
}

if ($node instanceof Closure) {
return $this->isVariableInClosureUses($node, $param->var);
if ($node instanceof Closure && $this->isVariableInClosureUses($node, $param->var)) {
$isParamUsed = true;
}

if (! $this->nodeNameResolver->isName($node, 'compact')) {
return false;
if ($this->isParamUsed($node, $param)) {
$isParamUsed = true;
}

$arguments = $this->funcCallManipulator->extractArgumentsFromCompactFuncCalls([$node]);
return $this->nodeNameResolver->isNames($param, $arguments);
return null;
});

return $isParamUsed;
}

/**
Expand Down Expand Up @@ -97,4 +111,31 @@ private function isVariableInClosureUses(Closure $closure, Variable $variable):

return false;
}

private function isUsedAsArg(Node $node, Param $param): bool
{
if ($node instanceof New_ || $node instanceof CallLike) {
foreach ($node->getArgs() as $arg) {
if ($this->nodeComparator->areNodesEqual($param->var, $arg->value)) {
return true;
}
}
}

return false;
}

private function isParamUsed(Node $node, Param $param): bool
{
if (! $node instanceof FuncCall) {
return false;
}

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

$arguments = $this->funcCallManipulator->extractArgumentsFromCompactFuncCalls([$node]);
return $this->nodeNameResolver->isNames($param, $arguments);
}
}
3 changes: 2 additions & 1 deletion src/PhpParser/Node/BetterNodeFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,9 @@ public function findFirstInFunctionLikeScoped(

$parentFunctionLike = $this->findParentByTypes(
$foundNode,
[ClassMethod::class, Function_::class, Closure::class]
[ClassMethod::class, Function_::class, Closure::class, Class_::class]
);

if ($parentFunctionLike !== $functionLike) {
return null;
}
Expand Down

0 comments on commit c3581f9

Please sign in to comment.