-
-
Notifications
You must be signed in to change notification settings - Fork 189
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
PHP 5.6 / 8.0: NewConstantDereferencing: add support for constant array / object dereferencing #1263
base: develop
Are you sure you want to change the base?
PHP 5.6 / 8.0: NewConstantDereferencing: add support for constant array / object dereferencing #1263
Conversation
…ay / object dereferencing > This RFC brings static scalar expressions to the parser. This allows places that only take static values (const declarations, ... etc) to also be able to take static expressions. > Constants... are currently special cased and only dereferencable under the `[]` operator (and do not even support the nominally equivalent `{}` operator). > > This RFC proposes to make constants (and class constants) fully array and object dereferencable, i.e. to allow both `FOO{0}` and `FOO->length()` (the latter only being relevant in conjunction with scalar objects). Ref: * https://wiki.php.net/rfc/const_scalar_exprs * php/php-src@d5ddd2d * https://wiki.php.net/rfc/variable_syntax_tweaks#constant_dereferencability Includes unit tests. Relates to PHPCompatibility#809.
Hi @elazar Finally... finally I've had a chance to properly look at this PR... sorry for the long wait. There's quite a lot to unpack here, so if you like, I'd be happy to talk things over in a call. About the PHP 5.6 change:As this change is related to the "constant arrays using Curly braces
I wonder if that is correct. The PHP 7.4 curly braces sniff So, again, I think some checking is needed whether curly braces were supported and under what circumstances and the tests should document the findings.
|
I confirmed that this change does apply to namespace and class constants. Namespace constants: https://3v4l.org/kUHCe
I confirmed that this change does NOT apply: curly braces on namespace and class constants produce a parse error in PHP < 8 and a fatal error in PHP >= 8. Namespace constants: https://3v4l.org/9CU6u I think I've integrated all other feedback (please let me know if I missed anything) with the exception of refactoring and/or integrating Thanks! |
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.
Hi Matthew, thanks for verifying the basis of the sniff.
I've gone through the sniff with a fine toothcomb now and left quite some comments in line, mostly just small touching up.
On the note of "small touching up": please use FQNs for global constants and function calls.
The more pregnant issues are the following:
public function addMatcher(MatcherInvocation $matcher): void {} // <- False positive.
class ORM implements \ArrayAccess {} // <- False positive.
echo 'print ', CONSTANT_NAME['foo']; // <- False negative.
echo 'print ', ClassName::CONST_NAME->bar; // Correctly detected.
echo 'print ', \NS_CONST[0]; // Correctly detected.
echo \Foo\BAR{0}; // <- False positive. Syntax is not supported in PHP, so out of scope of this sniff.
echo \Foo::BAR{0}; // <- False positive. Syntax is not supported in PHP, so out of scope of this sniff.
The majority of these issues can be fixed by adding an additional check to the "is this a reference" condition, like so:
if (!isset($referenceTokens[$nextNonEmptyCode])
|| ($nextNonEmptyCode === T_OPEN_CURLY_BRACKET && isset($tokens[$nextNonEmpty]['scope_opener']) === true)
) {
return;
}
The T_COMMA
can then also be removed from the $outOfScopeTokens
array, as well as quite a few other tokens.
I think it would also be good to add some tests with "double array dereferencing" to safeguard against potential upstream tokenizer issues:
echo FOO[0]['foo'];
echo \Foo\BAR['foo'][1];
echo \Foo::BAR[20]['bar'];
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
$tokens = $phpcsFile->getTokens(); | ||
|
||
// Not a reference, out of scope | ||
$referenceTokens = [ |
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.
Can this array be turned into a class property ? and as a property possibly given a value which would be helpful to do the check on line 114 and 126 ? (i.e. which error should be thrown for what)
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 array here contains T_OBJECT_OPERATOR
in addition to the other two tokens also used on 126. That would leave us doing something like this here:
if (!isset($this->referenceTokens[$nextNonEmptyCode])
&& $nextNonEmptyCode !== \T_OBJECT_OPERATOR) {
Is that what you had in mind?
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Tests/Syntax/NewConstantDereferencingUnitTest.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Tests/Syntax/NewConstantDereferencingUnitTest.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
PHPCompatibility/Sniffs/Syntax/NewConstantDereferencingSniff.php
Outdated
Show resolved
Hide resolved
@jrfnl Think I've resolved most your issues and left questions on the others. Let me know your thoughts and hopefully we can make the next round of feedback the last for this PR. Thanks! |
Ref:
Includes unit tests.
Relates to #809.