Skip to content
Open
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,31 @@
<?php

namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\CommandConfigureToAttributeRector\Fixture;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;

#[AsCommand(name: 'app:some')]
final class DescriptionWithNameOnExistingAttributeCommand extends Command
{
protected function configure(): void
{
$this->setDescription('Some description');
}
}

?>
-----
<?php

namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\CommandConfigureToAttributeRector\Fixture;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;

#[AsCommand(name: 'app:some', description: 'Some description')]
final class DescriptionWithNameOnExistingAttributeCommand extends Command
{
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\CommandConfigureToAttributeRector\Fixture;

use Symfony\Component\Console\Command\Command;

final class SkipNamePassedToParentConstructorCommand extends Command
{
public function __construct(?string $name = 'app:some')
{
parent::__construct($name);
}

protected function configure(): void
{
$this->setDescription('Some description');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Rector\Symfony\Tests\Symfony61\Rector\Class_\CommandConfigureToAttributeRector\Fixture;

use Symfony\Component\Console\Command\Command;

final class SkipNonConstantNameCommand extends Command
{
public function __construct(private readonly string $commandName)
{
parent::__construct();
}

protected function configure(): void
{
$this->setName($this->commandName);
$this->setDescription('Some description');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,17 @@ function (Arg $arg): string {
},
$attributeArgs
);

// #[AsCommand] requires a name: when there is something to move into the attribute but the name is neither
// on it already nor set by a constant setName() here (e.g. it is passed to the parent constructor),
// converting would produce an invalid attribute
if (! in_array('name', $existingAttributeNames, true)
&& ! $this->hasPermittedMethodCall($configureClassMethod, 'setName')
&& $this->hasPermittedAttributeMethodCall($configureClassMethod)
) {
return null;
}

$hasChanged = false;
foreach (self::METHODS_TO_ATTRIBUTE_NAMES as $methodName => $attributeName) {
$resolvedExpr = $this->findAndRemoveMethodExpr($configureClassMethod, $methodName);
Expand Down Expand Up @@ -293,6 +304,40 @@ private function findAndRemoveMethodExpr(ClassMethod $classMethod, string $metho
return $expr;
}

private function hasPermittedAttributeMethodCall(ClassMethod $classMethod): bool
{
foreach (array_keys(self::METHODS_TO_ATTRIBUTE_NAMES) as $methodName) {
if ($this->hasPermittedMethodCall($classMethod, $methodName)) {
return true;
}
}

return false;
}

private function hasPermittedMethodCall(ClassMethod $classMethod, string $methodName): bool
{
$hasMethodCall = false;

$this->traverseNodesWithCallable((array) $classMethod->stmts, function (Node $node) use (
&$hasMethodCall,
$methodName
): null {
if (! $node instanceof MethodCall || ! $this->isName($node->name, $methodName)) {
return null;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

early check :

if ($node->isFirstClassCallable()) {
    return null;
}

here ...

$args = $node->getArgs();
if ($args !== [] && $this->isPermittedAttributeValue($args[0]->value)) {
$hasMethodCall = true;
}

return null;
});

return $hasMethodCall;
}

private function isPermittedAttributeValue(Expr $expr): bool
{
if ($expr instanceof Scalar) {
Expand Down
Loading