-
-
Notifications
You must be signed in to change notification settings - Fork 89
Description
The problem
PHP 8.2 introduced Disjunctive Normal Form Types, which now adds parentheses to the tokens allowed within type declarations.
This is currently not yet supported by PHP_CodeSniffer and the PHP_CodeSniffer\Tokenizers\PHP class will not always handle tokens within DNF types correctly, which can lead to false positives/false negatives being reported for sniffs and incorrect fixes being made.
Typical issues in the Tokenizer:
- The
arraykeyword when used in a type declaration may not be retokenized fromT_ARRAYtoT_STRING. - The
true/false/nullkeywords when used in a type declaration may not be retokenized fromT_STRINGtoT_TRUE/T_FALSE/T_NULL. - The
&and|characters may not be retokenized toT_TYPE_UNION/T_TYPE_INTERSECTION.
Typical resulting sniff issues:
- Sniffs handling arbitrary parentheses spacing may act on parentheses in DNF types.
- Sniffs listening for the
arraykeyword may try to act on thearraykeyword when used in a DNF type. - Sniffs listening for bitwise and/or operators may act on the
&and|characters in DNF types. - etc
These issues also impact the functioning of the following PHPCS native helper functions and by extension all sniffs which use these methods:
File::getMethodParameters()(parameter types)File::getMethodProperties()(return types)File::getMemberProperties()(property types)File::isReference()
Compounding the Problem
Aside from the above, standards may want to treat (spacing around) parentheses in DNF types differently from (spacing around) parentheses used in other places in a code base.
Proposed Solution
To support DNF types the PHP_CodeSniffer\Tokenizers\PHP class will need significant updates.
When making these updates, I propose to include a change to retokenize the open and close parentheses when used in DNF types as T_TYPE_OPEN_PARENTHESIS and T_TYPE_CLOSE_PARENTHESIS respectively.
Having separate, PHPCS native tokens for the DNF parentheses will allow for sniff developers to decide on a case-by-case basis whether a sniff should or should not act on DNF parentheses.
This change also follows in the footsteps of the retokenization of the & and | tokens (when used in types) to T_TYPE_* tokens.
As part of this change, the new T_TYPE_OPEN_PARENTHESIS and T_TYPE_CLOSE_PARENTHESIS tokens will need to be handled correctly by the PHP_CodeSniffer\Tokenizers\Tokenizer class and tokens should get the parenthesis_opener, parenthesis_closer and nested_parenthesis tokens, same as if the tokens were the "normal" T_OPEN_PARENTHESIS and T_CLOSE_PARENTHESIS tokens.
Open question
As PHP 8.2 has been out for a while, some external standards may have implemented work-arounds for the current state of things.
So, aside from opinions on the above proposal itself, I would also like to hear opinions on when this change should be made.
- Should this change go into the next PHPCS 3.x minor (once the PR has been prepared) ?
- Or should this change go into PHPCS 4.0 ? (expected in 3-4 months)
/cc @asispts @dingo-d @fredden @GaryJones @greg0ire @kukulich @michalbundyra @Ocramius @sirbrillig @stronk7 @weierophinney @wimg