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
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
name: 'app:hello',
description: 'Greet the user.',
)]
class NameFromConstant extends Command
{
private const string ARGUMENT_NAME = 'name';

#[\Override]
protected function configure(): void
{
$this->addArgument(self::ARGUMENT_NAME, InputArgument::OPTIONAL, 'The name of the person to greet.');
}

#[\Override]
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument(self::ARGUMENT_NAME);
$output->writeln("Hello {$name}!");

return Command::SUCCESS;
}
}

?>
-----
<?php

namespace Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\Fixture;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
name: 'app:hello',
description: 'Greet the user.',
)]
class NameFromConstant
{
private const string ARGUMENT_NAME = 'name';

protected function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: self::ARGUMENT_NAME, description: 'The name of the person to greet.')]
?string $name, OutputInterface $output): int
{
$name = self::ARGUMENT_NAME;
Copy link
Contributor

@mickverm mickverm May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$name is now always 'name', this line should be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I think keep $name = $name is ok, then the deadCode set can handle that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$output->writeln("Hello {$name}!");
return Command::SUCCESS;
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use PhpParser\Node;
use PhpParser\Node\Attribute;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
Expand Down Expand Up @@ -235,7 +237,7 @@ private function removeConfigureClassMethod(Class_ $class): void

private function replaceInputArgumentOptionFetchWithVariables(ClassMethod $executeClassMethod): void
{
$this->traverseNodesWithCallable($executeClassMethod->stmts, function (Node $node): ?Variable {
$this->traverseNodesWithCallable($executeClassMethod->stmts, function (Node $node): null|Variable|ClassConstFetch|ConstFetch {
if (! $node instanceof MethodCall) {
return null;
}
Expand All @@ -251,6 +253,10 @@ private function replaceInputArgumentOptionFetchWithVariables(ClassMethod $execu
$firstArgValue = $node->getArgs()[0]
->value;

if ($firstArgValue instanceof ClassConstFetch || $firstArgValue instanceof ConstFetch) {
return $firstArgValue;
}

if (! $firstArgValue instanceof String_) {
// unable to resolve argument/option name
throw new ShouldNotHappenException();
Expand Down
Loading