-
-
Notifications
You must be signed in to change notification settings - Fork 205
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: review + bug fix for nullable types #1692
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
Merged
wimg
merged 8 commits into
develop
from
feature/removedoptionalbeforerequiredparam-review-and-bugfix
Mar 31, 2024
Merged
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: review + bug fix for nullable types #1692
wimg
merged 8 commits into
develop
from
feature/removedoptionalbeforerequiredparam-review-and-bugfix
Mar 31, 2024
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This was referenced Mar 17, 2024
…percase null No functional changes needed, this just is an extra safeguard that the sniff handles this correctly.
…sts/constant expressions Add some extra tests with `null` in the default value, but not as a stand-alone value, but as part of a constant expression. PHP itself will only evaluate constant expressions at runtime (when the function is called), not at compile time (when the deprecation is flagged). In practice, this means that a default value containing a constant expression which evaluates to `null` will always be flagged as deprecated by PHP if the parameter is before a required one and that the exception for typed properties with a `null` default does not apply to constant expressions. This means that the sniffs should also disregard any `null` token within a constant expression, as the only thing that's relevant is that case, is that there is a default value. Given that, the sniff is handling this correctly as-is. Also see: php/php-src#13752
…st cases ... in the false positives data provider. This will make some changes in follow-up commits easier.
…ional param, not the required param Originally, the sniff would walk from the first param to the last, keeping track of whether an optional parameter has been seen and flag any required parameter found after it. This commit changes the logic in the sniff to flag the actual issue with higher precision, by walking from the last parameter back to the first, keeping track of seen required parameters and flagging any optional parameters found before these. It also updates the error message to more closely match the error message used in PHP itself. PHP 8.0 would flag issues with "Deprecated: Required parameter $b follows optional parameter $a". As of PHP 8.1, the message was changed to read: "Deprecated: Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter".
…th PHP 8.1 new in initializers PHP 8.1 introduced the ability to use `new` in initializers. This now opens up the possibility that `null` is passed to an initializer. In practice though, this has no impact on the sniff as the "`new` object" is a default value making the parameter optional, so should still be flagged when used before a required parameter.
…e types / PHP 8.1 The [recent RFC proposing to deprecate implicit nullable types](https://wiki.php.net/rfc/deprecate-implicitly-nullable-types) brough an oversight in the `PHPCompatibility.FunctionDeclarations.RemovedOptionalBeforeRequiredParam` sniff to my attention. To quote [the RFC](https://wiki.php.net/rfc/deprecate-implicitly-nullable-types): > Even though signatures which contain an optional parameter before a required one were deprecated in PHP 8.0, the case of implicitly nullable types was left alone at that time due to BC concerns. This exclusion caused some bugs in the detection of which signatures should emit the deprecation notice. Indeed, the following signature only emits a deprecation as of PHP 8.1: > > `function bar(T1 $a, ?T2 $b = null, T3 $c) {}` At the time of writing this sniff this additional deprecation notice was not yet in place and was therefore not taken into account. This commit updates the sniff to _also_ throw deprecation notices for optional parameters before required ones, where the default value is `null` and the type is nullable. Includes unit tests safeguarding the fix. Ref: php/php-src@c939bd2
…ypes with null / PHP 8.3 The [recent RFC proposing to deprecate implicit nullable types](https://wiki.php.net/rfc/deprecate-implicitly-nullable-types) brough an oversight in the `PHPCompatibility.FunctionDeclarations.RemovedOptionalBeforeRequiredParam` sniff to my attention. To quote [the RFC](https://wiki.php.net/rfc/deprecate-implicitly-nullable-types): > Even though signatures which contain an optional parameter before a required one were deprecated in PHP 8.0, the case of implicitly nullable types was left alone at that time due to BC concerns. This exclusion caused some bugs in the detection of which signatures should emit the deprecation notice. > <snip> > And the signature that uses the generalized union type signature: > > `function test(T1 $a, T2|null $b = null, T3 $c) {}` > > only emits the deprecation notice properly as of PHP 8.3. At the time of writing this sniff this additional deprecation notice was not yet in place and was therefore not taken into account. This commit updates the sniff to _also_ throw deprecation notices for optional parameters before required ones, where the default value is `null` and the type is `null` or a union/DNF type which includes `null`. Includes unit tests safeguarding the fix. Refs: * php/php-src 11488 * php/php-src 11497 * php/php-src@68ef393
6bbbd4b to
34be846
Compare
Member
Author
|
Rebased and updated the commit message for the "FunctionDeclarations/RemovedOptionalBeforeRequiredParam: add extra tests/constant expressions" commit to document the PHP native behaviour better. |
wimg
approved these changes
Mar 31, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR replaces PR #1669
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: test with uppercase null
No functional changes needed, this just is an extra safeguard that the sniff handles this correctly.
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: add extra tests/constant expressions
Add some extra tests with
nullin the default value, but not as a stand-alone value, but as part of a constant expression.PHP itself will only evaluate constant expressions at runtime (when the function is called), not at compile time (when the deprecation is flagged).
In practice, this means that a default value containing a constant expression which evaluates to
nullwill always be flagged as deprecated by PHP if the parameter is before a required one and that the exception for typed properties with anulldefault does not apply to constant expressions.This means that the sniffs should also disregard any
nulltoken within a constant expression, as the only thing that's relevant is that case, is that there is a default value.Given that, the sniff is handling this correctly as-is.
Also see: php/php-src#13752
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: use named test cases
... in the false positives data provider.
This will make some changes in follow-up commits easier.
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: flag the optional param, not the required param
Originally, the sniff would walk from the first param to the last, keeping track of whether an optional parameter has been seen and flag any required parameter found after it.
This commit changes the logic in the sniff to flag the actual issue with higher precision, by walking from the last parameter back to the first, keeping track of seen required parameters and flagging any optional parameters found before these.
It also updates the error message to more closely match the error message used in PHP itself.
PHP 8.0 would flag issues with "Deprecated: Required parameter $b follows optional parameter $a".
As of PHP 8.1, the message was changed to read: "Deprecated: Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter".
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: add tests with PHP 8.1 new in initializers
PHP 8.1 introduced the ability to use
newin initializers. This now opens up the possibility thatnullis passed to an initializer.In practice though, this has no impact on the sniff as the "
newobject" is a default value making the parameter optional, so should still be flagged when used before a required parameter.FunctionDeclarations/RemovedOptionalBeforeRequiredParam: flag nullable types / PHP 8.1
The recent RFC proposing to deprecate implicit nullable types brough an oversight in the
PHPCompatibility.FunctionDeclarations.RemovedOptionalBeforeRequiredParamsniff to my attention.To quote the RFC:
At the time of writing this sniff this additional deprecation notice was not yet in place and was therefore not taken into account.
This commit updates the sniff to also throw deprecation notices for optional parameters before required ones, where the default value is
nulland the type is nullable.Includes unit tests safeguarding the fix.
Ref: php/php-src@c939bd2
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: flag union types with null / PHP 8.3
The recent RFC proposing to deprecate implicit nullable types brough an oversight in the
PHPCompatibility.FunctionDeclarations.RemovedOptionalBeforeRequiredParamsniff to my attention.To quote the RFC:
At the time of writing this sniff this additional deprecation notice was not yet in place and was therefore not taken into account.
This commit updates the sniff to also throw deprecation notices for optional parameters before required ones, where the default value is
nulland the type isnullor a union/DNF type which includesnull.Includes unit tests safeguarding the fix.
Refs:
FunctionDeclarations/RemovedOptionalBeforeRequiredParam: add documentation