Skip to content
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

feat: introduce PhpdocArrayStyleFixer #7781

Conversation

kubawerlos
Copy link
Contributor

@kubawerlos kubawerlos commented Jan 26, 2024

Resolves #4698

@coveralls
Copy link

coveralls commented Jan 26, 2024

Coverage Status

coverage: 94.759% (+0.008%) from 94.751%
when pulling e209068 on 6b7562617765726c6f73:add_PhpdocListTypeFixer
into 62280c4 on PHP-CS-Fixer:master.

* @param array<int> $b
* @param array<string, int> $c
- * @param list<int> $d
+ * @param array<int> $d
Copy link
Contributor

@bendavies bendavies Jan 26, 2024

Choose a reason for hiding this comment

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

this is not a list. it's array<array-key, int>

suggest removing this ['style' => 'array'] option

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👎🏼 for removing ['style' => 'array'], see #7077

maybe that option should not touch list<> and only change [] syntax 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Yes, the array|list should be used only when converting from [] syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It also should be possible to convert from array to list, should that be a separate option or included in list one?

Copy link
Contributor

@mvorisek mvorisek Jan 26, 2024

Choose a reason for hiding this comment

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

suggest removing this ['style' => 'array'] option

👍 plus the fixer should be renamed to reflect only the #7077 (ie. xxx[] to array<xxx>)

converting xxx[] to list<xxx> is really not possible by a fixer (without static analysis knowledge) as [] does simply not imply a list

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, even "maybe incorrect" changes on PHPDoc must be risky.

Copy link
Member

@Wirone Wirone Jan 26, 2024

Choose a reason for hiding this comment

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

Personally I don't consider it as risky because it does not break the code (it modifies comment, even if that comment is a part of a contract). The only thing that can be broken is SA in the QA process, but by default this fixer should make 1:1 change (from x[] to array<x>) and when someone opts-in for list the result is also expected. It can be used for detecting non-list arrays and allow fixing them, just like @kubawerlos did in the other PR.

I don't see the need for 2 fixers here and it was me who opted for a single, configurable fixer in private chat with @kubawerlos.

Copy link
Contributor

Choose a reason for hiding this comment

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

PHPDoc should be considered part of code. SA is part of code. reflection is part of code. So thus if PHPDoc change is risky, the fixer must be risky. Thus I belive two fixers would be better as xxx[] to array<xxx> is not risky, but array<xxx> to list<xxx> is risky.

Copy link
Member

Choose a reason for hiding this comment

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

@mvorisek every PHPStan update can cause new errors in SA, how's that different from making explicit decision about list when using this fixer? You do both on purpose. I wouldn't be too strict when it comes to riskiness of phpDoc changes... But the last word goes to @keradus anyway.

Copy link
Member

@keradus keradus Jan 29, 2024

Choose a reason for hiding this comment

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

my attention was grabbed outside of GH to look at this particular comment. I was not having a chance to look into all threads in this PR.

Should a fixer changing PHPDoc be risky?

You want to have 2 fixers - as it is in PHP CS Fixer: custom fixers - if so, then we can discuss the riskiness of the other in separate PR, but first let The One decide - @keradus - single, configurable fixer as in this PR or 2 separate fixers as you can see in PHP CS Fixer: custom fixers?

Riskiness is sth that can change the meaning. If we change type (regardless it's declared in code, phpdoc or attribute) to type that may have other meaning, it's risky.
With that, I would, myself, go with 2 fixers:

  • one converting array to list-or-iterable (maybe array to list is enough), eg array<int> -> list<int> (but not array<string, int> nor array{string, string, string}). This is Risky.
  • one converting array syntax - ie convert Foo[] to array<mixed, Foo> (not sure if I would go with array<Foo> as it is not. Probably yes to allow later risky conversion to list<Foo>). (and TBH I wonder if we need to support each possible conversion)

tests/AutoReview/FixerFactoryTest.php Outdated Show resolved Hide resolved
Comment on lines 73 to 74
'<?php /** @var list<bool>|list<float>|list<int>|list<string> */',
'<?php /** @var array<bool>|float[]|array<int>|string[] */',
Copy link
Member

Choose a reason for hiding this comment

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

array<T> should never be replaced with list<T> because they are not the same type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know these are not the same type, I don't get why, today, everyone thinks I don't.

To "forbid usage of Foo[] or array<Foo>" it needs to stay (maybe as 3rd option?) as in practice (see the long, first thread here, sponsored by 112 and 17) array<T> is often overused. Anyone carrying about the specific types must then add type to array<T> - if the keys matter, or have it converted to list<T> - if they don't.

Copy link
Member

Choose a reason for hiding this comment

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

I get your point but I think this rule should only focus on syntax, i.e. T[]array<T>. IMO forbidding array<T> is a matter of static analysis and out of scope here.

Copy link
Member

Choose a reason for hiding this comment

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

But I can see the scenario when developer wants to apply fixer with list as an target type, then run SA, fix not matching entries and keep the correct ones. Ability to apply it with a tool would save a lot of time in cases where there's more actual lists than arrays (comparing to applying array<> everywhere and converting to list<> manually).

tests/Fixer/Phpdoc/PhpdocListTypeFixerTest.php Outdated Show resolved Hide resolved
src/Fixer/Phpdoc/PhpdocListTypeFixer.php Outdated Show resolved Hide resolved
Copy link
Member

@Wirone Wirone left a comment

Choose a reason for hiding this comment

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

I did not review the code yet, but @bendavies pointed out that fixer's name is not correct, and I agree with him. Foo[] is not a list, it's an array with an undefined key type. Every list is an array, but not every array is a list, that's why the fixer's name should not focus on lists, but on arrays. Possible names:

  • PhpdocArrayTypeFixer
  • PhpdocArrayStyleFixer
  • PhpdocArrayTypeConventionFixer

@kubawerlos kubawerlos changed the title feat: introduce PhpdocListTypeFixer feat: introduce PhpdocArrayStyleFixer Jan 26, 2024
@kubawerlos
Copy link
Contributor Author

kubawerlos commented Jan 27, 2024

I've reworked the option - now everyone will find something for themselves.

When reviewing it further, please focus on:

  • technical solution. obviously
  • test cases, some tricky cases may still be missing
  • naming - fixer, option's name and values
  • wording - the description of the fixer and the option
  • default value of the option

Do NOT focus on:

  • suggesting removal of a strategy - remember, other people may have different preferences
  • explaining to the author the difference between different syntaxes - he understands them, as well as he also knows what it is like in practice

Copy link
Member

@Wirone Wirone left a comment

Choose a reason for hiding this comment

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

Some of the comments are rather for discussion, but at least the fixer's description should be improved.

PHP;

return new FixerDefinition(
'PHPDoc list types must be written in configured style.',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
'PHPDoc list types must be written in configured style.',
'PHPDoc array types must be written in configured style.',

Comment on lines +33 to +35
private const STRATEGY_FROM_ARRAY_TO_LIST = 'array_to_list';
private const STRATEGY_FROM_BRACKETS_TO_ARRAY = 'brackets_to_array';
private const STRATEGY_FROM_BRACKETS_TO_LIST = 'brackets_to_array_to_list';
Copy link
Member

Choose a reason for hiding this comment

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

Recently I am more and more convinced that we should use public consts as part of the contract, so people can use these in the config, instead of hardcoding string values. What do you think?

protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('strategy', 'Which part of the conversion - brackets (`[]`) to `array` to `list` - to perform.'))
Copy link
Member

Choose a reason for hiding this comment

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

Gramatically it's a bit weird, I would simplify it to something like:

Suggested change
(new FixerOptionBuilder('strategy', 'Which part of the conversion - brackets (`[]`) to `array` to `list` - to perform.'))
(new FixerOptionBuilder('strategy', 'Which type syntax should be used'))

Allowed values extends this information so it should be clear enough.

{
private const STRATEGY_FROM_ARRAY_TO_LIST = 'array_to_list';
private const STRATEGY_FROM_BRACKETS_TO_ARRAY = 'brackets_to_array';
private const STRATEGY_FROM_BRACKETS_TO_LIST = 'brackets_to_array_to_list';
Copy link
Member

Choose a reason for hiding this comment

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

I am wondering why it's not like this:

Suggested change
private const STRATEGY_FROM_BRACKETS_TO_LIST = 'brackets_to_array_to_list';
private const STRATEGY_FROM_BRACKETS_TO_LIST = 'brackets_to_list';

I am not sure we should include intermediate state in the strategy's name, I would rather use source-target convention.

src/Fixer/Phpdoc/PhpdocArrayStyleFixer.php Show resolved Hide resolved
@kubawerlos kubawerlos marked this pull request as draft January 30, 2024 22:23
@kubawerlos
Copy link
Contributor Author

Replaced by #7812

@kubawerlos kubawerlos closed this Feb 4, 2024
@kubawerlos kubawerlos deleted the add_PhpdocListTypeFixer branch February 4, 2024 08:23
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.

Rule to force syntax of array notation in PHPDocs
7 participants