Repository navigation
Conversation
…eToAttributeRector #[AsCommand] requires `name`. When configure() only sets a description, aliases or hidden, and the name is not on the attribute nor set by a constant setName() (it is passed to the parent constructor, for example), the rule created #[AsCommand(description: '...')], which throws ArgumentCountError when the container or the console boots. Leave such classes untouched. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
samsonasik
reviewed
Nov 4, 2026
| if (! $node instanceof MethodCall || ! $this->isName($node->name, $methodName)) { | ||
| return null; | ||
| } | ||
|
|
Member
There was a problem hiding this comment.
early check :
if ($node->isFirstClassCallable()) {
return null;
}here ...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CommandConfigureToAttributeRectormovessetName(),setDescription(),setAliases()andsetHidden()out ofconfigure()into#[AsCommand(...)]. It never checks that anameends up in the attribute.AsCommand::__construct()takes a requiredstring $nameas its first argument. When a command gets its name from somewhere else, for example the constructor:the rule currently produces
#[AsCommand(description: 'Some description')]. Compiling the container (or booting the console) then fails with:We hit this running the Symfony 6.0-7.2 sets on a Symfony 7.4 app: two commands got a nameless attribute and every
bin/consolecall crashed.Change
Before extracting anything, require that a name will be there: either already on an existing
#[AsCommand](name:) or set by a constantsetName()inconfigure(). If there is something to move into the attribute but no name, the class is left untouched (same approach as the existing skip for non-constant values).configure()bodies with nothing to move, likeempty_configure_body, still behave as before.Tests
New fixtures:
skip_name_passed_to_parent_constructor: the case above, left unchanged. Fails without the change.skip_non_constant_name:setName($this->commandName)next to a constant description, left unchanged. Fails without the change.description_with_name_on_existing_attribute:#[AsCommand(name: ...)]plus a description inconfigure()still converts (regression guard).The rule's tests pass (17), plus ECS and PHPStan.
🤖 Generated with Claude Code