-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
fix: PhpdocOrderFixer
when phpstan-
/ psalm-
order is specified
#8853
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: PhpdocOrderFixer
when phpstan-
/ psalm-
order is specified
#8853
Conversation
In v3.77.0, PhpdocOrderFixer added default support for ordering phpstan- and psalm- annotations after any of the equivalent non-prefixed tags that are specified. However, this produces incorrect diffs (unexpectedly reordering tags of the same type, and entirely removing multiline returns) if the user has specified an explicit order for these annotations. This commit proves the issue, to be followed by a separate fix.
In v3.77.0, PhpdocOrderFixer added default support for ordering phpstan- and psalm- annotations after any of the equivalent non-prefixed tags that are specified. If the user had already specified any of these tags in the order, the implementation was adding duplicates. E.g. a configuration like `['param', 'phpstan-param', 'return']` was internally processed as `['param', 'phpstan-param', 'phpstan-param', 'return']`. The duplicates were then causing annotations to be moved multiple times, in some cases resulting in them being deleted from the output (as proved by the testcase in the previous commit).
As the referenced Github Actions run from Behat/Gherkin will eventually be cleaned up, I have included the content below (I didn't want to add this to the main PR description to keep that readable). You can see that the fixer is suggesting completely deleting a complex Output from Behat/Gherkin fixer run in Github Actions
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
(would be nice to also have some test cases in PhpdocOrderFixerTest
for #8777 showing the reordering of the phpstan/psalm tags)
Add some cases to show the reordering of prefixed versions of specified annotations (introduced in PHP-CS-Fixer#8777 with only integration test coverage).
@gharlan thanks - I noticed the coverage in #8777 was a little light, but I wanted to keep this PR small initially. I've added a commit with a couple more test cases that I think cover the existing behaviour - I could obviously go into a lot more detail / break up the different things those examples are proving, but I'm not sure how complex you want this to get? The examples I've added felt in keeping with the existing test cases, but let me know if you'd like me to do anything more. I did also notice that #8777 causes some changes in the ordering of unspecified tags e.g. in the |
Thanks! I think that's enough. 👍 (I'm not a maintainer here, so let's wait for their feedback) |
Since php-cs-fixer@3.77.0, phpstan- prefixed annotations are by default ordered after the specified non-prefixed annotations. Therefore, we no longer need to explicitly configure an order for `@phpstan-param` and `@phpstan-return`. Additionally, specifying an order for these properties is currently causing our CI to fail with false diffs, due to a bug in php-cs-fixer. The fix in PHP-CS-Fixer/PHP-CS-Fixer#8853 will solve that, but since our ordering matches the default behaviour we can safely remove the redundant config rather than wait for that fix to get CI green again.
$configurationOrder[] = 'phpstan-'.$type; | ||
$configurationOrder[] = 'psalm-'.$type; | ||
if (!\in_array('phpstan-'.$type, $this->configuration['order'], true)) { | ||
$configurationOrder[] = 'phpstan-'.$type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback should be probably added after anything else.
Ex. when order is specified like param, phpstan-param
, with the current PR, param, psalm-param, phpstan-param
order will be kept, but I would expect param, phpstan-param, psalm-param
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's a reasonable point. Although I think there are potentially other cases where this behaviour can produce slightly-unexpected results especially if you specify order for some variants but not others.
Attempting to check & find the right insertion point for the prefixed variants would add even more overhead to this fixer at runtime - I'm not sure if that's desirable?
IMO the priority is to fix the bug in the current implementation (in particular that it can propose completely deleting annotations).
My gut feel is that it may be appropriate to say that if someone is using param, phpstan-param and psalm-param in the same project then they should either use the default ordering or specify all three in the order they want them.
I also encounter the issue. I'm using
To split classic phpdoc and static analysis phpdoc and now I end up which php cs fixer swapping phpdocs at every run. |
FWIW I believe @keradus just cherry-picked the implementation from a contributed PR. But it would be good to get the bugfix reviewed when possible - I'm very happy to make changes if required. |
PhpdocOrderFixer
when phpstan-
/ psalm-
order is specified
if (!\in_array('phpstan-'.$type, $this->configuration['order'], true)) { | ||
$configurationOrder[] = 'phpstan-'.$type; | ||
} | ||
if (!\in_array('psalm-'.$type, $this->configuration['order'], true)) { | ||
$configurationOrder[] = 'psalm-'.$type; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mvorisek are you happy with state of this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes 🟢
if (!\in_array('phpstan-'.$type, $this->configuration['order'], true)) { | ||
$configurationOrder[] = 'phpstan-'.$type; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kubawerlos are you happy with state of this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kubawerlos , you were recently touching logic around this. is this change (whole PR) valid for you ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to be consistent with the previous implementation (grouping the phpdoc and prefix related phpdoc) and avoiding the identified issues when prefix related phpdoc are already specified in the config. I think it's the best solution
Thank you @acoulton |
In v3.77.0 PhpdocOrderFixer added default support for ordering phpstan- and psalm- annotations after any of the equivalent non-prefixed tags that are specified. This was implemented in #8777, then optimised (with no behaviour change) in #8812.
However, this produces incorrect diffs (including unexpectedly reordering tags of the same type, and entirely removing multiline returns) if the user has specified an explicit order for these annotations.
This can be seen IRL in https://github.com/Behat/Gherkin/actions/runs/16302601436/job/46040722894 - unchanged code in master that was passing CS at the last merge is now failing and the proposed diff is invalid.
This is happening because the implementation from #8777 adds duplicates for any tags that the user had explicitly configured. E.g. a configuration like
['param', 'phpstan-param', 'return']
was internally processed as['param', 'phpstan-param', 'phpstan-param', 'return']
.These duplicates then cause annotations to be moved multiple times, in some cases resulting in them being deleted from the output.
This PR fixes the issue by ensuring that annotations are only added to the user-provided order if they are not already specified.