PHPCSStandards / PHP_CodeSniffer

PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.
BSD 3-Clause "New" or "Revised" License
880 stars 54 forks source link

4.0 | Proposal: add parameter types to methods in PHPCS #390

Open jrfnl opened 6 months ago

jrfnl commented 6 months ago

Setting the scene

PHPCS 4.0 will have a minimum supported PHP version of PHP 7.2.

PHP 7.2 allows for:

PHP 7.2 does not support:

Parameter type declarations in PHP are contravariant, which means that overloaded methods in child classes can widen the type. Return type declarations in PHP are covariant, which means that overloaded methods in child classes can make the type more narrow.

Full support for contravariance and covariance was only added in PHP 7.4, but for the purposes of this proposal, the partial support as added in PHP 7.2 should be sufficient.

Proposal

I propose to update the signatures of the following public/protected methods in PHPCS 4.0, adding (additional) parameter type declarations as per the list below.

Detailed proposal

Notes about the detailed proposal:

In PHP_CodeSniffer\Config:

In PHP_CodeSniffer\Fixer:

In PHP_CodeSniffer\Reporter:

In PHP_CodeSniffer\Ruleset:

In PHP_CodeSniffer\Runner:

In PHP_CodeSniffer\Files\File:

In PHP_CodeSniffer\Files\DummyFile:

In PHP_CodeSniffer\Files\FileList:

In PHP_CodeSniffer\Filters\Filter:

In PHP_CodeSniffer\Filters\Git*:

In PHP_CodeSniffer\Generators\Generator:

In PHP_CodeSniffer\Generators\*:

All methods taking a $node parameter will be updated to expect DOMElement instead of DOMNode.

In PHP_CodeSniffer\Reports\Report:

In PHP_CodeSniffer\Sniffs\Sniff:

In PHP_CodeSniffer\Sniffs\AbstractArraySniff:

In PHP_CodeSniffer\Sniffs\AbstractPatternSniff:

In PHP_CodeSniffer\Sniffs\AbstractScopeSniff:

In PHP_CodeSniffer\Sniffs\AbstractVariableSniff:

In PHP_CodeSniffer\Tokenizers\Tokenizer:

In PHP_CodeSniffer\Tokenizers\Comment:

In PHP_CodeSniffer\Tokenizers\PHP:

In PHP_CodeSniffer\Util\Cache:

In PHP_CodeSniffer\Util\Common:

In PHP_CodeSniffer\Util\Standards:

In PHP_CodeSniffer\Util\Timing:

In PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest:

Regarding strict types

This proposal explicitly does NOT include adding strict_types=1 declarations to the classes/interfaces in PHP_CodeSniffer.

PHPCS can not enforce for external standards to add strict_types, which means that strict_types offers a false sense of security as it is only effective when both the file in which the method call is made, as well as the file containing the method being called has a strict_types declaration.

In all other situations, it will still end up juggling the type of a passed parameter for scalar types and throw a TypeError for non-scalar types.

Additionally, for users using external standards which do already use strict_types, it is likely to lead to more problems with files not being scanned correctly/completely due to type issues when exceptions are not being caught. Also see #30.

I propose discussing enabling strict_types for PHPCS in a separate issue with a target PHPCS version of 5.0 or higher.

Future scope

After this proposal there will still be a few parameters untyped due to those needing the mixed type or a union/intersection/DNF type.

After this proposal has been actioned, a follow-up issue should be opened to keep track of what remains and to action adding types to those parameters depending on when PHPCS will raise the minimum supported PHP version to the version needed for those parameters.

BC considerations

As parameter types are contravariant, adding these type declarations in PHPCS 4.0 does not break backward compatibility.

An overloaded/implemented method in a child class which does not have a type declaration, effectively widens the type to mixed.

Suggested Migration Path for External Standards

During the lifetime of PHPCS 4.x, external standards are encouraged to:

None of this can/will be enforced, but external standards using the lifetime of PHPCS 4.x to action the above will be better prepared for supporting PHPCS 5.x when the time comes.

Opinions ?

/cc @asispts @dingo-d @fredden @GaryJones @greg0ire @kukulich @michalbundyra @Ocramius @sirbrillig @stronk7 @weierophinney @wimg

sirbrillig commented 6 months ago

As with the return types issue, I think that the more types, the safer the code and the more clear the API, so I vote in favor of this.

stronk7 commented 6 months ago

I like it. Just, side comment… maybe this could be considered as an opportunity to advance marking what’s public API and what’s not, in case #392 is delayed too much? It could help identifying stuff then.

Ciao :)

asispts commented 6 months ago

I like the idea :+1:. PHP 7 will show a warning about the incompatibility, which can be used by CS owners/maintainers to fix their code.

maybe this could be considered as an opportunity to advance marking what’s public API and what’s not, in case #392 is delayed too much? It could help identifying stuff then.

Agreed.

weierophinney commented 6 months ago

@jrfnl One note: you can add parameter types in a minor release without being a BC break. Extensions/implementations can widen argument parameters without violating the LSP, and if they were previously leaving them untyped, the implied type is mixed.

(In FIG, we even codified this in the PSR Evolution bylaw.)

So you might be able to introduce these in v3, and then use v4 as the BC break introducing return types.

jrfnl commented 6 months ago

So you might be able to introduce these in v3, and then use v4 as the BC break introducing return types.

@weierophinney PHPCS 3.x still has a minimum of PHP 5.4, so that's not an option. The minimum PHP version will be raised to PHP 7.2 in PHPCS 4.0, which is why this proposal targets that version for parameter types and #391 targets 5.0 for return types.