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

Generic/PHPDocTypes and PSR5/PHPDocTypes: Adds sniffs #469

Closed

Conversation

james-cnz
Copy link

Description

Adds sniffs for PHPDoc types, both a generic sniff, and one for conformance to the PHP-FIG PSR-5 rules relating to types (using the generic sniff, with different properties set).

PHPStan and Psalm are the two most commonly used PHP type checkers, and phpDocumentor is moving to base it's type handling off PHPStan, while PHPStorm uses Psalm for type checking. My feeling is that types that are accepted by both PHPStan and Psalm are essentially de facto valid PHPDoc types, so the generic checks aim to check that types meet these criteria.

The PSR-5 sniff only checks rules relating to types.

The checker handles all type-related tags (property-*, template, param, return, and var). I think this makes sense, because it's likely that it will be desired to check all types by the same standard.

Type comparisons are performed between PHPDoc types and PHP natives types, where present. It isn't perfect, because the checker is only aware of a single file at a time, and can't recognise global constants, but I think it's fairly good for what it is. It takes account of namespaces, use aliases, and class hierarchies in the current file. While PHPStan and Psalm will do much better checking, they are easiest to set up for code that adheres to OO principles, and may produce spurious errors for code that makes use of require/include(_once), so the type-checking feature of this sniff may be useful in these cases.

The sniff can check for misplaced type tags, except for misplaced var tags. My understanding is that var tags are appropriate where a variable is first declared, which can include an assignment, as a foreach loop variable, or being returned as a pass-by-reference parameter where one wasn't passed in. The sniff doesn't attempt to check this.

I originally wrote this for the Moodle Coding Style project, but I think it may be more broadly useful, so am submitting it here instead.

Suggested changelog entry

  • Added Generic.Commenting.PHPDocTypes sniff
    • Aims to check that PHPDoc types will be parsed by both PHPStan and Psalm.
  • Added PSR5.Commenting.PHPDocTypes sniff
    • Checks that PHPDoc types conform to PHP-FIG PSR-5.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
    • This change is only breaking for integrators, not for external standards or end-users.
  • Documentation improvement

PR checklist

  • I have checked there is no other PR open for the same change.
  • I have read the Contribution Guidelines.
  • I grant the project the right to include and distribute the code under the BSD-3-Clause license (and I have the right to grant these rights).
  • I have added tests to cover my changes.
  • I have verified that the code complies with the projects coding standards.
  • [Required for new sniffs] I have added XML documentation for the sniff.

Adds sniffs for PHPDoc types, both a generic sniff, and one for conformance to the PHP-FIG PSR-5 rules relating to types (using the generic sniff, with different properties set).
@jrfnl
Copy link
Member

jrfnl commented Apr 27, 2024

@james-cnz Thank you for your willingness to contribute to PHP_CodeSniffer and I can see you've put a huge amount of work into this.

However, this PR does a lot of things, including adding a new standard, new utility class and two new sniffs. The main sniff itself has the same problems as the pre-existing sniffs: it does too much. Aside from that, it is nearly certain that it will conflict with the existing Variable/Function comment sniffs and will make it impossible to use a combination.

All in all, I'm not keen on this PR as-is. All of this should have been discussed in an issue first as per the contributing guide on New features.

@jrfnl
Copy link
Member

jrfnl commented Apr 27, 2024

For reference a previous discussion on this work as it was first pulled to an external standard: moodlehq/moodle-cs#123

@james-cnz
Copy link
Author

I understand that it's generally desirable to divide the checking up into different sniffs, so users can select the ones they want. With the type tags, though, I think users are most likely to want to check them all in the same way, or check none of them. e.g. If users want to check the var type tag for conformance to PHP-FIG's PSR-5, then they're most likely to want to check all type tags for this conformance. Dividing the checking into different sniffs wouldn't be beneficial here, I think.

Yes, I think it would conflict with the existing sniffs, but I think they serve somewhat different use cases. The proposed sniffs aim to check either that types will be parsed by PHPStan and Psalm, or that types conform to PHP-FIG's PSR-5, while the existing sniffs check for conformance to their own standard, I think? As part of supporting PHPStan and Psalm types, the proposed checker supports types that span multiple lines, include the $this type, and include variables specified as part of a callable type, as well as functions that annotate only some parameters. I don't think the existing sniffs support these things, so they might not be used in the same cases. The PSR-5 standard and the existing sniffs flatly contradict, I think, PSR-5 requiring short type names, and the existing sniffs requiring long ones, so these couldn't be used together.

My apologies for not posting first. I assumed this would be to avoid me carrying out unnecessary work if the sniff wasn't wanted, and figured that since I'd done most of the work already, it probably didn't apply.

@jrfnl
Copy link
Member

jrfnl commented Apr 28, 2024

I assumed this would be to avoid me carrying out unnecessary work if the sniff wasn't wanted, and figured that since I'd done most of the work already, it probably didn't apply.

@james-cnz Those guidelines are there for a reason and yes, preventing unnecessary work is part of that reason, but not the only reason for that guideline. You are new to this repo and have no history of contributing to this project. Your PR demonstrates a lack of familiarity with the project, with the codebase, with established best practices, with the history and the envisioned future.
Coaching this PR in the direction where it should be going in would take months and the chance of it ever getting to a merge-ready place are slim.

PHPCS allows for external standards. As things are, I suggest you'd be better off creating your own external standard where you can do things your way.
As a side-note, I'd recommend not using PSR5 as a ruleset name in an non-sanctioned external standard as that is likely to come back and bite you in the future when there will be a sanctioned PSR5 standard.

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

Successfully merging this pull request may close these issues.

2 participants