Skip to content

[composer-based] Add composer-based command - #8246

Merged
TomasVotruba merged 1 commit into
mainfrom
composer-based-command
Jul 31, 2026
Merged

[composer-based] Add composer-based command#8246
TomasVotruba merged 1 commit into
mainfrom
composer-based-command

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

Rules can bind themselves to an installed package version via ComposerPackageConstraintInterface, and ComposerPackageConstraintFilter silently drops the ones that do not match. There was no way to see which rules those are, or why a rule did not run.

New composer-based command:

vendor/bin/rector composer-based

Run in rector-phpunit with PHPUnitSetList::COMPOSER_BASED loaded:

Composer package bound rules
============================

 ------------------------------------------------------------------------ ----------------- ---------- ----------- --------
  Rule                                                                     Package           Requires   Installed   Active
 ------------------------------------------------------------------------ ----------------- ---------- ----------- --------
  ...\ClassMethod\DataProviderAnnotationToAttributeRector                  phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\ClassMethod\DependsAnnotationWithValueToAttributeRector              phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\ClassMethod\TestWithAnnotationToAttributeRector                      phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\Class_\AnnotationWithValueToAttributeRector                          phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\Class_\CoversAnnotationWithValueToAttributeRector                    phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\Class_\RequiresAnnotationWithValueToAttributeRector                  phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\Class_\TicketAnnotationToAttributeRector                             phpunit/phpunit   >=10.0     13.2.6.0    yes
  ...\PHPUnit110\Rector\CallLike\AssertContainsOnlyMethodCallRector        phpunit/phpunit   >=11.5     13.2.6.0    yes
  ...\PHPUnit110\Rector\ClassMethod\MockObjectArgCreateStubToCreateMockRector  phpunit/phpunit   >=11.0     13.2.6.0    yes
  ...\PHPUnit120\Rector\Class_\AssertIsTypeMethodCallRector                phpunit/phpunit   >=11.5     13.2.6.0    yes
 ------------------------------------------------------------------------ ----------------- ---------- ----------- --------

 ! [NOTE] 10 of 10 composer package bound rules are active

Columns:

  • Requires - the constraint the rule declares in provideComposerPackageConstraint()
  • Installed - the version resolved from the analysed project, - when the package is not installed
  • Active - whether ComposerPackageConstraintFilter will keep the rule

Inactive rules are listed too, which is the point - a rule missing from the run is now visible with the reason next to it.

Covered by ComposerBasedCommandTest - the empty case, an active rule, and a rule whose package is not installed.

@TomasVotruba TomasVotruba changed the title [Console] Add composer-based command [composer-based] Add composer-based command Jul 31, 2026
@TomasVotruba
TomasVotruba merged commit 7442c9e into main Jul 31, 2026
65 checks passed
@TomasVotruba
TomasVotruba deleted the composer-based-command branch July 31, 2026 19:54
@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

I just updated to the latest version, ran vendor/bin/rector composer-based and got:

PHP Fatal error:  Uncaught Error: Typed property PHPStan\Type\UnionType::$normalized must not be accessed before initialization in /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php:161
Stack trace:
#0 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(161): ReflectionProperty->getValue(Object(PHPStan\Type\UnionType))
#1 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(161): Rector\Console\Command\ComposerBasedCommand->printConfigurationValue(Object(PHPStan\Type\UnionType))
#2 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(147): Rector\Console\Command\ComposerBasedCommand->printConfigurationValue(Object(Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration))
#3 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(118): Rector\Console\Command\ComposerBasedCommand->printConfiguration(Array)
#4 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(57): Rector\Console\Command\ComposerBasedCommand->createConfigurationTableRows()
#5 /app/vendor/rector/rector/vendor/symfony/console/Command/Command.php(289): Rector\Console\Command\ComposerBasedCommand->execute(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#6 /app/vendor/rector/rector/vendor/symfony/console/Application.php(911): RectorPrefix202608\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#7 /app/vendor/rector/rector/vendor/symfony/console/Application.php(279): RectorPrefix202608\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Console\Command\ComposerBasedCommand), Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#8 /app/vendor/rector/rector/src/Console/ConsoleApplication.php(79): RectorPrefix202608\Symfony\Component\Console\Application->doRun(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#9 /app/vendor/rector/rector/vendor/symfony/console/Application.php(162): Rector\Console\ConsoleApplication->doRun(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#10 /app/vendor/rector/rector/bin/rector.php(132): RectorPrefix202608\Symfony\Component\Console\Application->run()
#11 /app/vendor/rector/rector/bin/rector(5): require_once('/var/www/pimcor...')
#12 /app/vendor/bin/rector(119): include('/var/www/pimcor...')
#13 {main}
  thrown in /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php on line 161
Fatal error: Uncaught Error: Typed property PHPStan\Type\UnionType::$normalized must not be accessed before initialization in /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php:161
Stack trace:
#0 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(161): ReflectionProperty->getValue(Object(PHPStan\Type\UnionType))
#1 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(161): Rector\Console\Command\ComposerBasedCommand->printConfigurationValue(Object(PHPStan\Type\UnionType))
#2 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(147): Rector\Console\Command\ComposerBasedCommand->printConfigurationValue(Object(Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration))
#3 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(118): Rector\Console\Command\ComposerBasedCommand->printConfiguration(Array)
#4 /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php(57): Rector\Console\Command\ComposerBasedCommand->createConfigurationTableRows()
#5 /app/vendor/rector/rector/vendor/symfony/console/Command/Command.php(289): Rector\Console\Command\ComposerBasedCommand->execute(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#6 /app/vendor/rector/rector/vendor/symfony/console/Application.php(911): RectorPrefix202608\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#7 /app/vendor/rector/rector/vendor/symfony/console/Application.php(279): RectorPrefix202608\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Console\Command\ComposerBasedCommand), Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#8 /app/vendor/rector/rector/src/Console/ConsoleApplication.php(79): RectorPrefix202608\Symfony\Component\Console\Application->doRun(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#9 /app/vendor/rector/rector/vendor/symfony/console/Application.php(162): Rector\Console\ConsoleApplication->doRun(Object(RectorPrefix202608\Symfony\Component\Console\Input\ArgvInput), Object(RectorPrefix202608\Symfony\Component\Console\Output\ConsoleOutput))
#10 /app/vendor/rector/rector/bin/rector.php(132): RectorPrefix202608\Symfony\Component\Console\Application->run()
#11 /app/vendor/rector/rector/bin/rector(5): require_once('/var/www/pimcor...')
#12 /app/vendor/bin/rector(119): include('/var/www/pimcor...')
#13 {main}
  thrown in /app/vendor/rector/rector/src/Console/Command/ComposerBasedCommand.php on line 161

@TomasVotruba

Copy link
Copy Markdown
Member Author

Can you share PHPStan and PHP version?

@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

PHP: 8.4.23
PHPStan: 2.2.6

@TomasVotruba

Copy link
Copy Markdown
Member Author

Thanks. Nothing rings a bell.
Can you share min rector.php that is causing it?

@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Just tried with PHPStan 2.2.7 — same error.

@TomasVotruba

Copy link
Copy Markdown
Member Author

How's the Rector and PHPStan installed? Composer, Docker, global, dev etc.

@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Both via composer.

@TomasVotruba

Copy link
Copy Markdown
Member Author

Can you share min rector.php that is causing it?

@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

I cleared the cache — didn't help.

I get the error with just this minimal config:

return RectorConfig::configure()
    ->withComposerBased(symfony: true)
;

I have Symfony 7.4.15 installed.

@jdreesen

jdreesen commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

When I remove symfony, like:

return RectorConfig::configure()
    ->withComposerBased(twig: true, doctrine: true, phpunit: true)
;

it works!

@TomasVotruba

Copy link
Copy Markdown
Member Author

I tried it locally and that's the issue. I'm looking into it 👍

@TomasVotruba

Copy link
Copy Markdown
Member Author

PR in progress: #8280

@TomasVotruba

Copy link
Copy Markdown
Member Author

Fixed and released: https://github.com/rectorphp/rector/releases/edit/2.6.1

Many new rules landed in the Symfony and Twig sets now. Let me know if you find any new issues 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants