Skip to content

[Php80] Handle multiple ->ruleWithConfiguration() call in same rule on AnnotationToAttributeRector#4831

Closed
samsonasik wants to merge 3 commits intomainfrom
failing-fixture
Closed

[Php80] Handle multiple ->ruleWithConfiguration() call in same rule on AnnotationToAttributeRector#4831
samsonasik wants to merge 3 commits intomainfrom
failing-fixture

Conversation

@samsonasik
Copy link
Copy Markdown
Member

@samsonasik samsonasik commented Aug 22, 2023

@TomasVotruba @lucasmirloup this is failing fixture for multiple calls ->ruleWithConfiguration() on same rector rule which should merge instead of replace:

    $rectorConfig
        ->ruleWithConfiguration(AnnotationToAttributeRector::class, [
            new AnnotationToAttribute('Doctrine\ORM\Mapping\Entity'),
        ]);

    // should merge with existing config
    $rectorConfig
        ->ruleWithConfiguration(AnnotationToAttributeRector::class, [
            new AnnotationToAttribute('Doctrine\ORM\Mapping\ManyToMany'),
        ]);

Fixes rectorphp/rector#8150
Ref https://getrector.com/demo/d196b918-b061-4c2d-a439-7058e88e6e57

@samsonasik
Copy link
Copy Markdown
Member Author

I am debugging ->ruleWithConfiguration() method, it seems the method is replaced instead of merged:

➜  rector-src git:(failing-fixture) vendor/bin/phpunit rules-tests/Php80/Rector/Class_/AnnotationToAttributeRector/MultipleCallAnnotationToAttributeRectorTest.php
PHPUnit 10.3.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.5
Configuration: /Users/samsonasik/www/rector-src/phpunit.xml

array (1)
   0 => Rector\Php80\ValueObject\AnnotationToAttribute #1984
   |  tag: 'Doctrine\ORM\Mapping\Entity'
   |  attributeClass: null

array (1)
   0 => Rector\Php80\ValueObject\AnnotationToAttribute #1981
   |  tag: 'Doctrine\ORM\Mapping\ManyToMany'
   |  attributeClass: null

F                                                                   1 / 1 (100%)

Time: 00:00.250, Memory: 58.00 MB

There was 1 failure:

@samsonasik
Copy link
Copy Markdown
Member Author

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba the possible solution is to use array_merge(), but the another rules may probably require same apply:

     public function configure(array $configuration): void
     {
         Assert::allIsAOf($configuration, AnnotationToAttribute::class);
-        $this->annotationsToAttributes = $configuration;
+        $this->annotationsToAttributes = array_merge($this->annotationsToAttributes, $configuration);

any idea to make it general on other rules as well?

@samsonasik samsonasik changed the title [Php80] Add failing fixture multiple ->ruleWithConfiguration() call in same rule on AnnotationToAttributeRector [Php80] Handle multiple ->ruleWithConfiguration() call in same rule on AnnotationToAttributeRector Aug 22, 2023
@samsonasik
Copy link
Copy Markdown
Member Author

@lucasmirloup I fixed with add new RECTOR_CONFIGURATION parameter to be merged with existing config 4f7622f

@TomasVotruba the existing rules-tests may need update based on this change.

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba with this change, individual test is somehow working ok on rector-symfony, but not work on run all:

➜  rector-symfony git:(main) ✗ vendor/bin/phpunit tests/Set/Symfony44/Symfony44Test.php
PHPUnit 10.3.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.5
Configuration: /Users/samsonasik/www/rector-symfony/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 00:00.567, Memory: 60.00 MB

OK (1 test, 2 assertions)
➜  rector-symfony git:(main) ✗ vendor/bin/phpunit 
PHPUnit 10.3.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.5
Configuration: /Users/samsonasik/www/rector-symfony/phpunit.xml

..............F................................................  63 / 403 ( 15%)
............................................................... 126 / 403 ( 31%)
............................................................... 189 / 403 ( 46%)
............................................................... 252 / 403 ( 62%)
............................................................... 315 / 403 ( 78%)
............................................................... 378 / 403 ( 93%)
.........................                                       403 / 403 (100%)

Time: 00:10.361, Memory: 224.50 MB

There was 1 failure:

1) Rector\Symfony\Tests\Set\Symfony44\Symfony44Test::test with data set #0
Failed on fixture file "event_fixture.php.inc"
Failed asserting that string matches format description.
--- Expected
+++ Actual
@@ @@
 
 class SomeEventListener
 {
-    public function someMethod(\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $exceptionEvent)
+    public function someMethod(\Symfony\Component\HttpKernel\Event\ExceptionEvent $exceptionEvent)

so it somehow reset on some area.

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba Ok, the change is expected on all run on rector-symfony, as

symfony 4.4 = symfony 4.3 + symfony 4.4

merged.

@samsonasik
Copy link
Copy Markdown
Member Author

Oh, it's not, symfony-44 is not merge of symfony-43 and symfony-44 so when enter new test class, it should reset the Option::RECTOR_CONFIGURATION values.

So the Option::RECTOR_CONFIGURATION values need to be tweaked for reset on enter new tests class.

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba let's tweak with reset value in tearDownAfterClass() 8ba0d70

@samsonasik
Copy link
Copy Markdown
Member Author

Finally, it works @TomasVotruba @lucasmirloup 🎉 🎉 🎉 All checks have passed 🎉 🎉 🎉 @TomasVotruba I think it is ready.

@TomasVotruba
Copy link
Copy Markdown
Member

This should be handled internally by the beforeResolving() or afterResolving() method of Laravel container.

I'll look into it

@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Aug 23, 2023

Rebased, @TomasVotruba how about merge as is for now and improve in separate PR?

This already tweak on $this->afterResolving() on the ruleWithConfiguration() usage https://github.com/rectorphp/rector-src/pull/4831/files#diff-7670175f1f1c668d4a1611d0e211d616b84d433c7b8280f88900fe1445e5b792

@TomasVotruba
Copy link
Copy Markdown
Member

TomasVotruba commented Aug 23, 2023

No need to rush this one, as it better be fixed correctly than re-patched. The rules should be registered just once, maybe that will help:

$isBound = $this->bound($rectorClass);

        // avoid double registration
        if ($isBound === false) {
            $this->singleton($rectorClass);
            $this->tagRectorService($rectorClass);
        }

You can try these checks in rule() and ruleWithConfiguraiton() methods.



I'm looking into this, but experience some infinite loops while running this test. How do tests work for you? :)

@TomasVotruba
Copy link
Copy Markdown
Member

I'm looking into this, but experience some infinite loops while running this test. How do tests work for you? :)

Seems this fixed it, there was infinite loop without the illuminate/container patch:

composer install

@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Aug 23, 2023

$isBound doesn't work for me, the $configuration need to be merged with existing one from the exact equal service, so ->configure() need to be re-called again with existing values

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba to reproduce, you can run the following test:

vendor/bin/phpunit rules-tests/Php80/Rector/Class_/AnnotationToAttributeRector/MultipleCallAnnotationToAttributeRectorTest.php

@samsonasik
Copy link
Copy Markdown
Member Author

@TomasVotruba it has nothing todo with service registered once or many times, the configurable rules need to call ->configure() to fill array property, and the array property need to be merged with existing one for exact rule if the ->ruleWithConfiguration() called again, that usually happen when multiple import used so it should be merged instead of replaced, that's why ->configure() need to be re-called with bring existing value when exists.

@samsonasik
Copy link
Copy Markdown
Member Author

The ->singleton() method already make service registered only once afaik. The ->configure() need to be recalled to merge with existing property value instead of replace, that's why SimpleParameterProvider is needed to merge with existing configurable value for exact service index

$configurableRector->configure($configuration);

SimpleParameterProvider::addParameter(Option::RECTOR_CONFIGURATION, [
$rectorClass => $configuration,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The $rectorClass as configurable index is essential here, to be re-used to merge with existing service config on next ->ruleWithConfiguration() called.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AnnotationToAttributeRector misbehaves since v0.18.0

2 participants