diff --git a/rules-tests/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector/Fixture/skip_assign_no_discard_method_call.php.inc b/rules-tests/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector/Fixture/skip_assign_no_discard_method_call.php.inc new file mode 100644 index 00000000000..754972eff93 --- /dev/null +++ b/rules-tests/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector/Fixture/skip_assign_no_discard_method_call.php.inc @@ -0,0 +1,17 @@ +some_call(); + } + + #[\NoDiscard] + private function some_call() + { + + } +} diff --git a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php index 1fe9691bd89..eadfc71a7bb 100644 --- a/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php +++ b/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.php @@ -12,6 +12,10 @@ use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\Include_; +use PhpParser\Node\Expr\MethodCall; +use PhpParser\Node\Expr\New_; +use PhpParser\Node\Expr\NullsafeMethodCall; +use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Class_; @@ -25,6 +29,8 @@ use Rector\NodeAnalyzer\VariableAnalyzer; use Rector\NodeManipulator\StmtsManipulator; use Rector\Php\ReservedKeywordAnalyzer; +use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; +use Rector\PhpParser\AstResolver; use Rector\PhpParser\Enum\NodeGroup; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\Rector\AbstractRector; @@ -42,7 +48,9 @@ public function __construct( private readonly SideEffectNodeDetector $sideEffectNodeDetector, private readonly VariableAnalyzer $variableAnalyzer, private readonly BetterNodeFinder $betterNodeFinder, - private readonly StmtsManipulator $stmtsManipulator + private readonly StmtsManipulator $stmtsManipulator, + private readonly AstResolver $astResolver, + private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer ) { } @@ -265,6 +273,18 @@ function (Node $subNode) use (&$refVariableNames) { continue; } + if ($assign->expr instanceof FuncCall + || $assign->expr instanceof StaticCall + || $assign->expr instanceof MethodCall + || $assign->expr instanceof New_ + || $assign->expr instanceof NullsafeMethodCall) { + $targetCall = $this->astResolver->resolveClassMethodOrFunctionFromCall($assign->expr); + if (($targetCall instanceof ClassMethod || $targetCall instanceof Function_) + && $this->phpAttributeAnalyzer->hasPhpAttribute($targetCall, 'NoDiscard')) { + continue; + } + } + $assignedVariableNamesByStmtPosition[$key] = $variableName; } diff --git a/rules/Php80/NodeAnalyzer/PhpAttributeAnalyzer.php b/rules/Php80/NodeAnalyzer/PhpAttributeAnalyzer.php index b76e243b90b..264b0c246a0 100644 --- a/rules/Php80/NodeAnalyzer/PhpAttributeAnalyzer.php +++ b/rules/Php80/NodeAnalyzer/PhpAttributeAnalyzer.php @@ -12,6 +12,7 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Property; use Rector\NodeNameResolver\NodeNameResolver; use Rector\PhpAttribute\Enum\DocTagNodeState; @@ -23,7 +24,7 @@ public function __construct( ) { } - public function hasPhpAttribute(Property | ClassLike | ClassMethod | Param $node, string $attributeClass): bool + public function hasPhpAttribute(Property | ClassLike | ClassMethod | Function_ | Param $node, string $attributeClass): bool { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attribute) { @@ -41,7 +42,7 @@ public function hasPhpAttribute(Property | ClassLike | ClassMethod | Param $node /** * @param string[] $attributeClasses */ - public function hasPhpAttributes(Property | ClassLike | ClassMethod | Param $node, array $attributeClasses): bool + public function hasPhpAttributes(Property | ClassLike | ClassMethod | Function_ | Param $node, array $attributeClasses): bool { foreach ($attributeClasses as $attributeClass) { if ($this->hasPhpAttribute($node, $attributeClass)) { diff --git a/src/PhpParser/AstResolver.php b/src/PhpParser/AstResolver.php index 392b22b2f29..3b1047bde6f 100644 --- a/src/PhpParser/AstResolver.php +++ b/src/PhpParser/AstResolver.php @@ -112,7 +112,7 @@ function (Node $node) use ($classLikeName, $methodName, &$classMethod): bool { } public function resolveClassMethodOrFunctionFromCall( - FuncCall | StaticCall | MethodCall | New_ $call + FuncCall | StaticCall | MethodCall | New_ | NullsafeMethodCall $call ): ClassMethod | Function_ | null { if ($call instanceof FuncCall) { return $this->resolveFunctionFromFuncCall($call);